[Qt开发]一口气搞懂串口通信

这篇具有很好参考价值的文章主要介绍了[Qt开发]一口气搞懂串口通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🐊🐊🐊🐊🐊好多小鳄鱼

一、关于串口通信:

Qt的确有自己的串口通信类,就是QSerialPort,但是我们在使用过程中因为要更加定制化的使用串口通信类减小开发的难度,所以我们会提供一个串口通信类,也就是这个SerialPortHelper类。

首先我们要知道什么是串口,串口通信就是机器和系统之间的一个通信协议,你可以将它理解为共享内存,可以根据需要向其中写入内容,然后在需要的时候从中读取数据。不过需要注意的是,在Qt的封装下,你不需要知道串口内的数据是否是给你的,还是你发的,因为统统都是你的。

串口通信什么?

大概了解了一下什么是串口通信,那么我们来看一下串口通信的通信手册大概是什么样。

[Qt开发]一口气搞懂串口通信

由上我们可以看到,串口通信消息大概就是一串16进制的字符按照特定的规定,然后向串口中写入这些消息就可以了。比如前面这三个41 54 64这三个数字就是固定写死的,而36则是这个协议的通信号,是用于区分不同消息码的,比如上述这条指令的消息码是36,另外一条消息

然后后续标了颜色的内容就是实际上这条消息码中具体携带的数据,这个就不过多介绍了。

不过需要注意的是,硬件返回的数据或者向硬件发送的数据不一定都是像人一样的从左到右,有些命令特别是偏长的命令很多都是要求从右到左,也就是常说的小端序,低字节在前高字节在后,比如:
[Qt开发]一口气搞懂串口通信

给出两端函数示例(实际上这两个函数在Qt中都有,这里只是展示一下具体是什么意思而已):

//将接收到的小端字节序数据转换为无符号整数
QString SerialPortHelper::getLittleEnd(const QByteArray& data)
{
	if (data.size() > 8) return "";
	qulonglong result = 0;
	for (int i = 0; i < data.size(); ++i)
	{
		qulonglong tmp = (uchar)data[i];
		result += tmp <<= i * 8;
	}
	return QString::number(result);
}

//大端字节序数据转换为浮点数
QString SerialPortHelper::getBigEndFlt(const QByteArray& data)
{
	const int fltLen = 4;
	if (data.size() != fltLen) return "null";
	float result = 0;
	uchar fltArr[fltLen];
	for (int i = 0; i < fltLen; ++i)
	{
		fltArr[fltLen - i - 1] = data.at(i);
	}
	return QString::number(*(float*)fltArr, 'f', 9);
}

ok,接下来还有四位数字,这个要分开来说前两位和后两位。

其中前两位是CRC校验码,这个是需要对前面的数字进行一个基本的校验,具体我就不太懂了,这里提供一个函数,供参考:

void SerialPortHelper::CRC16_2(const QByteArray& ba, uchar* crcBuf)
{
	int pos, i;
	uchar* buf = (uchar*)ba.data();
	int len = ba.size();
	unsigned int crc = 0xFFFF;
	for (pos = 0; pos < len; pos++)
	{
		crc ^= (unsigned int)buf[pos]; // XOR byte into least sig. byte of crc
		for (i = 8; i != 0; i--) // Loop over each bit
		{
			if ((crc & 0x0001) != 0) // If the LSB is set
			{
				crc >>= 1; // Shift right and XOR 0xA001
				crc ^= 0xA001;
			}
			else // Else LSB is not set
			{
				crc >>= 1; // Just shift right
			}
		}
	}
	//高低字节转换
	crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
	//qDebug() << QString().sprintf("CRC:%04x", crc);
	crcBuf[0] = crc >> 8;
	crcBuf[1] = crc;
}

最后两位就是固定的了,用两个固定搭配来分割各种字符段

串口通信使用流程

我们一般使用串口类,主要流程如下:

1.获得基本参数:
我们需要获得这个串口的一些基本参数,其中包含内容如下:

QString portName = "NULL";
int baudRate = 921600;
QSerialPort::DataBits dataBits = QSerialPort::Data8;
QSerialPort::StopBits stopBits = QSerialPort::OneStop;
QSerialPort::Parity parity = QSerialPort::NoParity;

我们需要在启动这个端口调用的时候设置好这些属性,才能获取正确的COM口消息和发送消息,给出一个启动串口的示例:

serialPort = new QSerialPort();
serialPort->setPortName(param.portName);
if (serialPort->open(QIODevice::ReadWrite))
{
	serialPort->setBaudRate(param.baudRate);
	serialPort->setDataBits(param.dataBits);
	serialPort->setStopBits(param.stopBits);
	serialPort->setParity(param.parity);
	//通知串口接收到消息的信号函数
	connect(serialPort, &QSerialPort::readyRead, this, &CarControlModel::dataReceive);	
	qDebug() << "connect:" << param.portName;
	emit checkConnableRetSig(true);

	setStartTime();
	//emit comConnStatus(true);
	return true;

See?其实很简单的的,这个对象实际上就做了一件事,通知你现在来数据了。注意,这个readyRead 并不是发给你接到的数据,而是通知你现在串口接到消息了,而且这个消息还很有可能不是一条一条的,可能是一段一段的,就是消息可能不完整,这里给出一个示例。

void CarControlModel::dataReceive()
{
	if (serialPort != nullptr && serialPort->isOpen())
	{

		QByteArray buffer = serialPort->readAll();
		analysisData(buffer);
	}
}

void CarControlModel::analysisData(const QByteArray& dataArr)
{
	//消息断开的情况
	qDebug() << "recv data: " << dataArr.toHex(' ');
	dataBuff.append(dataArr);
	QList<QByteArray> dataList;
	for (;;)
	{
		int index = dataBuff.indexOf(QByteArray(gEnd, gEndLen));
		if (index == -1) break;
		dataList.append(dataBuff.mid(0, index + gEndLen));
		dataBuff = dataBuff.right(dataBuff.size() - index - gEndLen);
	}
	if (dataList.size() == 0) return;
	。。。。

也就是说,接到串口指令之后可能还需要你做一个解析,把接到的消息拆分出来处理。

向串口发送指令:

发送指令的话,就比较简单了,比如:文章来源地址https://www.toymoban.com/news/detail-479370.html

qint64 CarControlModel::startCentralCMD()
{
	QByteArray allArr, funDataArr;
	funDataArr.clear();
	funDataArr.append(0x32);
	funDataArr.append(0x01);  //0x01启动中心码盘
	code(allArr, funDataArr);
	return writeData(allArr);
}

//传入功能码数据区,组合成完整的指令存入数组
void CarControlModel::code(QByteArray& allArr, const QByteArray& funDataArr)
{
	allArr.clear();
	allArr.append(gId, gIdLen);
	allArr.append(gAddress, gAddressLen);
	allArr.append(funDataArr);
	uchar crcBuf[gCrcLen];
	CRC16_2(allArr, crcBuf);
	allArr.append((char*)crcBuf, gCrcLen);
	allArr.append(gEnd, gEndLen);
}
//串口发送消息出去
qint64 CarControlModel::writeData(const QByteArray& data)
{
	qDebug() << "send data: " << data.toHex(' ');
	qint64 ret = -1;
	if (serialPort != nullptr && serialPort->isOpen())
	{
		ret = serialPort->write(data);
		if (!serialPort->waitForBytesWritten(10000))
		{
			//emit sendWarningSig("发送失败:" + data.toHex(' '));
			qDebug() << QString("发送失败:" + data.toHex(' '));
		}
	}
	else
	{
		emit sendWarningSig("工控主串口未连接");
	}
	return ret;
}

到了这里,关于[Qt开发]一口气搞懂串口通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大手笔!吴恩达一口气开放了 3 个 AIGC 教程。。

    公众号关注 “GitHubDaily” 设为 “星标”,每天带你逛 GitHub! 一个月前,DeepLearning.ai 创始人吴恩达与 OpenAI 开发者 Iza Fulford 联手推出了一门面向开发者的技术教程:《 ChatGPT 提示工程 》。 该教程总共分为 9 个章节,总一个多小时,里面主要涵盖:提示词最佳实践、评论情

    2024年02月11日
    浏览(56)
  • 一口气整理三种不同二维码生成的Java 接入代码

    二维码已经成为现代社会中广泛应用的一种工具,它们具有快速、可靠和高容量的信息传递能力。通过扫描二维码,用户可以轻松获取网址、产品信息、支付链接等各种信息。 本文将介绍二维码生成器 API 作为一种工具,并探讨其功能和用法,包括普通二维码生成、带图片的

    2024年02月06日
    浏览(45)
  • 4月更新!EasyOps®全平台27项新功能一口气来袭~

    又到了每月产品盘点时刻,27大新功能上线和升级优化,设计Hyperlnsight超融合持续观测平台、DevOps持续交付平台、AutoOps自动化运维平台、ITSM服务平台、公共服务,在不断的技术创新过程中,进一步加速IT运维效率升级。 下面和小编一起来了解本次更新详情吧! Hyperlnsight 1)

    2023年04月27日
    浏览(31)
  • 卧剿,6万字!30个方向130篇!CVPR 2023 最全 AIGC 论文!一口气读完。

    一杯奶茶,成为 AIGC+CV 视觉前沿弄潮儿! 25个方向!CVPR 2022 GAN论文汇总  35个方向!ICCV 2021 最全GAN论文汇总 超110篇!CVPR 2021 最全GAN论文梳理 超100篇!CVPR 2020 最全GAN论文梳理   在最新的视觉顶会 CVPR 2023 会议中,涌现出了大量基于 生成式AIGC 的CV论文,包括不限于 生成对抗

    2024年02月09日
    浏览(48)
  • 让ChatGPT做一下MySQL 8.0 OCP(1Z0-908)的真题,我松了一口气

    MySQL OCP分成中文和英文两种,Oracle OCP只有英文考试,这里我们用MySQL 8.0 OCP(1Z0-908)的中文真题测试一下ChatGPT,看看ChatGPT能否获得MySQL OCP的认证,用这种方法判断ChatGPT会不会代替我们人类DBA的工作。 1报告在MySQL服务器上运行的所有当前连接,ChatGPT准确地列出了3个: SELECT

    2024年02月04日
    浏览(51)
  • 又一巨头宣布入局AIGC,一口气开源数个模型,还道出了它的变现之道

    金磊 发自 凹非寺 量子位 | 公众号 QbitAI AIGC (AI生成内容),这个概念在今年可以说是火得一塌糊涂。 例如Stable Diffusion,只要对它说一句话,“唰唰唰”地就能秒生成画作。 再如最近大火的ChatGPT,对答如流堪比人类,简直让网友们玩得不亦乐乎。 △ 左:Stable Diffusion作画;

    2024年02月10日
    浏览(42)
  • 【万字详细教程】Linux to go——装在移动硬盘里的Linux系统(Ubuntu22.04)制作流程;一口气解决系统安装/引导文件迁移/显卡驱动安装等问题

    如果不想看前面的废话😭,请跳转到 1.准备工具 处开始阅读。 制作基于PSSD的Linux to go系统是我很早就打算做的事情,但这毕竟不是常规的装系统,因此在这之前我也调研了许多经验贴,不过我的思路是找到一个看起来最靠谱而且步骤相对简单的帖子,然后一路跟着走下去。

    2024年02月22日
    浏览(110)
  • 【Qt上位机与STM32进行串口通信】-2-Qt串口开发

    系列文章目标:Qt上位机与STM32进行串口通信,控制多个LED的状态。 本篇文章的主要目标: 1、设计两个界面,串口连接界面、控制界面。 2、只有在串口连接成功才能打开控制界面。 3、打开控制界面时,串口保持连接。 4、自定义控件,提升开发效率。 以下是我入门Qt的视频

    2024年02月06日
    浏览(46)
  • 【Visual Studio】使用 C++ 语言,配合 Qt,开发了一个串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 我要使用的功能比较简单,主要包含扫描串口、打开串口、发送数据、接收数据、暂停按钮、停止按钮,因此接下里将围绕这几个功能依次更新。 我的工程项目名字叫 “GUI”。

    2024年02月11日
    浏览(68)
  • 【Visual Studio】Qt 的实时绘图曲线功能,使用 C++ 语言,配合 Qt 开发串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 战斗背景:做了个串口接收界面,用来接收传输过来的信号。但是光用数字显示太单调,需要用图线显示出来。 战略目标:干掉它。 战术路线:Qt 绘图可以使用 Qt Charts,先了解

    2024年02月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包