Qt 官方串口库QSerialPort的 readyRead() 信号,只要有数据就抛出,这就导致一条数据分多次抛出。由于正常的数据没有固定的开头和结尾,这就导致无法获取正常的一组数据。
解决思路:增加接收延时功能,把多次读取的数据保存到缓冲区,延时结束,一次性读取数据
示例:
QSerialPort *serialPort= new QSerialPort();
connect(serialPort, SIGNAL(readyRead()), this, SLOT(slotReadData()));
void MainWindow::slotReadData()
{
static QByteArray sumData;
QByteArray tempData = serial->readAll();
if(!tempData.isEmpty())
{
sumData.append(tempData);
if(sumData.contains("\n")) // 检测到换行符
{
do_DataHandler(sumData); // 数据解析
sumData.clear();
}
}
tempData.clear();
}
void MainWindow::do_DataHandler(QByteArray BufferData)
{
/* *
*
* 筛选出“{x,yyyyyy}”格式的数据
*
* */
//异常类:无头且变量为空,已丢失头部,数据不可靠,直接返回
if ((!BufferData.contains("{"))&(PasteData.isNull()))
{
return;
}
//第一种:有头无尾,先清空原有内容,再附加
if ((BufferData.contains("{"))&(!BufferData.contains("}")))
{
PasteData.clear();
PasteData.append(BufferData);
}
//第二种:无头无尾且变量已有内容,数据中段部分,继续附加即可
if ((!BufferData.contains("{"))&(!BufferData.contains("}"))&(!PasteData.isNull()))
{
PasteData.append(BufferData);
}
//第三种:无头有尾且变量已有内容,已完整读取,附加后输出数据,并清空变量
if ((!BufferData.contains("{"))&(BufferData.contains("}"))&(!PasteData.isNull()))
{
PasteData.append(BufferData);
ReadData = PasteData;
PasteData.clear();
}
//第四种:有头有尾(一段完整的内容),先清空原有内容,再附加,然后输出,最后清空变量
if ((BufferData.contains("{"))&(BufferData.contains("}")))
{
PasteData.clear();
PasteData.append(BufferData);
ReadData = PasteData;
PasteData.clear();
}
QString MidStr;
QStringList list= ReadData.split("{");
for(int i=0; i < list.length();i++)
{
if(!list.at(i).isEmpty())
{
MidStr = list.at(i);
if(!MidStr.isEmpty())
{
MidStr.insert(0, '{');
//qDebug() << "ReadData:" << ReadData;
qDebug() << "MidStr:" << MidStr;
}
}
}
ReadData.clear();
}
解决思路:增加接收延时功能,把多次读取的数据保存到缓冲区,延时结束,一次性读取数据
示例:
QByteArray baRcvData;
QSerialPort *serialPort= new QSerialPort();
QTimer *timer = new QTimer();
connect(serialPort, SIGNAL(readyRead()), this, SLOT(slotReadData()));
connect(timer, SIGNAL(timeout()), this, SLOT(timeUpdate())));
void MainWindow::slotReadData()
{
timer->start(100);//启动定时器,接收100毫秒数据(根据情况设定)
baRcvData.append(serialPort->readAll());
}
void MainWindow::timeUpdate()
{
timer->stop();
if(baRcvData.length()!=0)
{
qDebug()<<baRcvData;
}
baRcvData.clear();
}