熟悉QT开发的朋友应该都知道,在开发QT串口应用程序的时,会遇到接收数据不完整的情况,这是因为串口是异步收发,而默认情况下QSerialPort
没有对串口收进行阻塞,所以才会出现串口数据接收不完整的情况。
解决办法很简单:在接收槽那儿开一个定时器,做一段小延时OK 了,即延时接收,时间大概10~30ms,看自己的程序进行微调
连接槽函数并扫描计算机串口设备:
//连接槽
connect(&timer, SIGNAL(timeout()), this, SLOT(serialRead())); //连接定时器槽,计时结束读出所有串口缓冲器数据;
//获取计算机上所有串口并添加到comboBox中
QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();
if(infos.isEmpty())
{
ui->serialCom->addItem("无可用串口");
return;
}
ui->textBrowser->appendPlainText("发现可用串口:");
foreach (QSerialPortInfo info, infos) {
ui->serialCom->addItem(info.portName());
Serial_list.append(info.portName());
ui->textBrowser->appendPlainText(info.portName());
}
初始化并打开串口:
//初始化并打开串口
void Widget::on_serialConnect_clicked()
{
QSerialPortInfo info;
QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();
int i = 0;
ui->disConnect->setEnabled(true); //使能断开按钮
ui->serialConnect ->setEnabled(false); //失能连接按钮
//初始化串口;
if(i != infos.size ()){//can find
ui->textBrowser->appendPlainText("串口打开成功"+tr("\n"));
serial.setPortName(ui->serialCom->currentText());
serial.open(QIODevice::ReadWrite); //读写打开
serial.setBaudRate(QSerialPort::Baud9600); //波特率
serial.setDataBits(QSerialPort::Data8); //数据位
serial.setParity(QSerialPort::NoParity); //无奇偶校验
serial.setStopBits(QSerialPort::OneStop); //无停止位
serial.setFlowControl(QSerialPort::NoFlowControl); //无控制
serial_flag = 1; //打开串口,标志为1;
ui->connectStatus->setText(tr("串口已打开"));
QMessageBox::information(this, tr("串口配置"), tr("串口已打开!"));
}else{
serial.close();
ui->textBrowser->appendPlainText("串口打开失败");
}
}
开启定时器,延时接收:
void Widget::com_delay()
{
//启动定时器,延时15~30ms 等待数据接收完成;
timer.start(15);
datagram.append(serial.readAll());
qDebug() << tr("开始串口接收");
}
读出并打印数据:
void Widget::serialRead()
{
const char toHex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//定时器停止
timer.stop();
qDebug() << tr("串口接收完成!");
if(datagram.length() != 0)
{
ui->textBrowser->insertPlainText(tr("\n\n【收到数据来自:")+serial.portName()+tr(":")+tr("】\n"));
//循环打印接收到的数据;
for(int i=0;i<datagram.size();i++){ //for 循环解析、打印;
char ch = datagram.at(i);
QString tmpStr="";
tmpStr.append(toHex[(ch&0xf0)/16]);
tmpStr.append(toHex[ch&0x0f]);
tmpStr.append(" ");
ui->textBrowser->insertPlainText(tmpStr);
}
qDebug() << datagram;
}
// QMessageBox::warning (this,tr("提示信息"),tr("串口接收成功"));
rcvDataCnt+=datagram.size();
ui->ReceiveEdit->setText(QString::number(rcvDataCnt,10));
datagram.clear(); //读取完成之后需要对接收数组进行清空操作;
}
总结:
以上代码就是针对QT串口延时接收数据的操作,其中toHex
数组加入的目的是为了显示十六进制的流式数据,因为在QT的打印串口中,显示的数据类型是QString
类型,我这里使用了一个for
循环,遍历转换数据类型,非常方便实用,很有参考意义。
版权属于:编码书生
本文链接:https://codess.cc/archives/369.html
所有原创文章采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
除特别注明,您可以自由的转载和修改,但请务必注明文章来源且不可用于商业目的。