1. 现象
//正常数据
Read: "12345678901234567890123456789012345678901234567890"
//异常数据
Read: "12345678901234567890123456789012"
Read: "345678901234567890"
2. 问题代码
#include "serialbase.h"
QString serialNameLinux = "/dev/ttyS4";
SerialBase::SerialBase(QObject *parent)
: QObject{parent}
{
// 设置串口号
SerialPort.setPortName(serialNameLinux);
// 打开串口
SerialPort.open(QIODevice::ReadWrite);
// 设置波特率
SerialPort.setBaudRate(115200);
//设置数据位数
SerialPort.setDataBits(QSerialPort::Data8);
//设置奇偶校验
SerialPort.setParity(QSerialPort::NoParity);
// 设置流控制
SerialPort.setFlowControl(QSerialPort::NoFlowControl);
//设置停止位
SerialPort.setStopBits(QSerialPort::OneStop);
}
SerialBase::~SerialBase()
{
SerialPort.close();
}
void SerialBase::serialRx(void)
{
SerialPort.waitForReadyRead(10);
QByteArray rxBuff = SerialPort.readAll();
if(rxBuff.length() > 0)
qDebug() << "Read: " << rxBuff;
}
//周期性调用这个函数
void SerialBase::serialReadTest()
{
serialRx();
}
3. 问题分析
- 问题出在
SerialPort.waitForReadyRead(10);
这行代码,手册中的说明如下:
- 超时时间到达之前接收到数据,则发送信号
readyRead()
,超时时间到达的时候,返回true
。 - 注意,如果超时时间到达时,数据帧没有接收完,就出现了如上问题。
- 超时时间到达时还没有数据返回,则直接返回
false
4. 解决思路
接收到readyRead()
信号后,再调用waitForReadyRead()
等待一段时间。
4. 修改后代码
#include "serialbase.h"
QString serialNameLinux = "/dev/ttyS4";
SerialBase::SerialBase(QObject *parent)
: QObject{parent}
{
// 设置串口号
SerialPort.setPortName(serialNameLinux);
// 打开串口
SerialPort.open(QIODevice::ReadWrite);
// 设置波特率
SerialPort.setBaudRate(115200);
//设置数据位数
SerialPort.setDataBits(QSerialPort::Data8);
//设置奇偶校验
SerialPort.setParity(QSerialPort::NoParity);
// 设置流控制
SerialPort.setFlowControl(QSerialPort::NoFlowControl);
//设置停止位
SerialPort.setStopBits(QSerialPort::OneStop);
//接收到数据后,再等待一段时间
connect(&SerialPort, SIGNAL(readyRead()), this, SLOT(waitNextMs()));
}
SerialBase::~SerialBase()
{
SerialPort.close();
}
void SerialBase::serialRx(void)
{
SerialPort.waitForReadyRead(10);
QByteArray rxBuff = SerialPort.readAll();
if(rxBuff.length() > 0)
qDebug() << "Read: " << rxBuff;
}
void SerialBase::waitNextMs()
{
SerialPort.waitForReadyRead(20);
qDebug() << "wait";
}
void SerialBase::serialReadTest()
{
serialRx();
}