Qt串口接收数据不全

运行环境

版本:Qt5.14

IDE:QtCreator

问题描述

我使用的是readyRead()信号触发接收函数,使用serial->readAll()进行数据读取。在一台电脑上使用虚拟串口工具生成串口,使用串口助手每10ms发送一个262个字符的数据,不会发生接收数据不全的问题。

接着使用两台电脑,两个串口模块连接进行测试,同样速率和数据,接收到的数据会一段一段的到达。

处理方法

  1. 如果数据有帧头和帧尾,使用全局缓冲区,将接收到的数据放进缓冲区,判断是否满足整包,满足再进行包处理,不满足一直接数据

QByteArray Port_buffer;//需要定义在.h类里作为全局变量,不能放函数里

//下面是.cpp里
QByteArray data = serial->readAll();
Port_buffer.append(data);
if(Port_str.startsWith("FFFAFFFA")&&Port_str.contains("ED\r\n"))//帧头FFFAFFFA,帧尾ED
{
    //缓冲区里数据以FFFAFFFA开头,并且包含一个ED\r\n,表明至少有一个完整包
    index_ED = Port_buffer.indexOf("ED\r\n");//定位到帧尾的位置
    QByteArray pack = Port_buffer.left(index_ED+4);//取一个包的数据
    Port_buffer.remove(0,index_ED+4);
    //去空格、检查数据包
    //数据处理
}else if(!Port_str.startsWith("FFFAFFFA")&&Port_buffer.contains("FFFAFFFA"))
    {
        //不以FFFAFFFA开头,说明数据不完整,如果里面包含数据头,则直接删除到数据头的位置
        Port_buffer.remove(0,Port_buffer.indexOf("FFFAFFFA"));
    }

上面方式存在一个问题:使用虚拟串口本地测,不会发生数据分段接收,每次都是一个完整的数据进来,上面代码每次只允许一次,会发生Port_buffer里一直存数据包,时间长了就蹦了,处理方法:可以把接收改成定时处理。但是虚拟串口也只是理想情况,我的软件肯定是通过串口线连接到另外一台设备,所以这样应该也是可以的

上图data是从串口中取出的数据,直到存满完整数据才进行数据处理

上图使用虚拟串口,每次触发readyread都至少有一整个数据包(可能因为界面还在刷新数据等原因导致串口里滞留多个数据包),但是只触发一次读取数据,导致缓冲区里数据处理不完,这里可以用定时处理方式解决。

2.如果没有帧头帧尾,可以判断是否以\r\n结尾,判断是否收到一个完整数据包

if(Port_str.endsWith("\r\n"))//修改成endsWith("\r\n")就可以判断是否结束
{

}

其他

考虑过增加串口接收线程,但是代码会很复杂,上图里每2ms就能触发一次读数据,说明绰绰有余。我的界面刷新数据也是每次接收都刷新,还画个曲线图,再加上每10ms发个包,都能接收的过来。

建议:除非需要多个串口同时接数据,需要使用到多线程。如果只有一个串口接数据,就别折腾多线程了。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt串口接收数据可以通过Qt的SerialPort模块来实现。首先需要在Qt工程中添加SerialPort模块的头文件,然后创建一个QSerialPort对象来进行串口的配置和数据接收。 具体步骤如下: 1. 引入SerialPort模块的头文件: #include <QtSerialPort/QtSerialPort> 2. 创建一个QSerialPort对象: QSerialPort serial; 3. 配置串口参数: serial.setPortName("串口名称"); // 设置串口名称,如"COM1"或"/dev/ttyUSB0"等 serial.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serial.setDataBits(QSerialPort::Data8); // 设置数据位数 serial.setParity(QSerialPort::NoParity); // 设置奇偶校验 serial.setStopBits(QSerialPort::OneStop); // 设置停止位 serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 4. 打开串口: serial.open(QIODevice::ReadOnly); // 以只读方式打开串口 5. 监听串口数据的到达: connect(&serial, SIGNAL(readyRead()), this, SLOT(readData())); 6. 实现数据接收槽函数: void MyClass::readData() { QByteArray data = serial.readAll(); // 读取串口缓冲区中的所有数据 // 对接收到的数据进行处理 ... } 通过以上步骤,可以实现Qt串口数据接收。接收到的数据可以通过读取QByteArray对象的方法进行处理,比如获取数据长度、将数据转换为字符串等。 需要注意的是,在使用串口通信时,还需要注意安装操作系统相关的串口驱动程序,并且确认所选用的串口号及串口参数与对应的设备匹配。此外,如果需要发送数据,还可以通过QSerialPort的write方法来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值