之前一章学习的是第三方库使用: 34.QT-qextserialport第三方库制作串口助手(并动态检测在线串口,附带源码)
本章来学习自带serial库
1.QSerialPortInfo
QList<QSerialPortInfo> QSerialPortInfo::availablePorts(); //获取当前在线的串口设备
示例如下:
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { qDebug() << "Name : " << info.portName(); qDebug() << "Description : " << info.description(); qDebug() << "Manufacturer: " << info.manufacturer(); qDebug() << "Serial Number: " << info.serialNumber(); qDebug() << "System Location: " << info.systemLocation(); }
2.QSerialPort初始化
初始化如下所示:
serialport.setPortName(cfg.portName); serialport.setBaudRate(QSerialPort::Baud115200); serialport.setParity(QSerialPort::NoParity); serialport.setDataBits(QSerialPort::Data8); serialport.setStopBits(QSerialPort::OneStop); serialport.setFlowControl(QSerialPort::NoFlowControl); if(!serialport.open(QIODevice::ReadWrite)) { qDebug()<<"打开失败"; return; }
3.QSerialPort信号介绍
void readyRead(); //当串口接收到下位机发送数据时,将会发送该信号,然后我们在对应的槽函数调用serialport .readAll()即可 error(QSerialPort::SerialPortError ); //串口错误信号,比如当串口打开失败,串口连接时突然断开,都将会调用该信号 //比如: QSerialPort::PermissionError (表示串口连接断开了)
4.QSerialPort示例
Widget::Widget(QWidget *parent) : QWidget(parent), serialport(this), btn("发送",this) { serialport.setPortName("COM21"); serialport.setBaudRate(QSerialPort::Baud115200); serialport.setParity(QSerialPort::NoParity); serialport.setDataBits(QSerialPort::Data8); serialport.setStopBits(QSerialPort::OneStop); serialport.setFlowControl(QSerialPort::NoFlowControl); if(!serialport.open(QIODevice::ReadWrite)) { qDebug()<<"打开失败"; return; } connect(&serialport,SIGNAL(readyRead()),this,SLOT(onReadyRead())); connect(&btn,SIGNAL(clicked()),this,SLOT(sendSerialData())); } void Widget::onReadyRead() { QString str(serialport.readAll()); qDebug()<<str; } void Widget::sendSerialData() { serialport.write(QString("发送:%1 ").arg(qrand()).toLocal8Bit()); //发送随机值 }
运行打印:
发现下位机发送上来的是乱码的,这是因为我们下位机程序是用的gbk编码写的,所以打印汉字乱码了
5.修改代码-添加数据格式编码转换
修改发送/接收函数:
void Widget::onReadyRead() { QString str(fromGBKtoUtf8(serialport.readAll())); QStringList list = str.split(QRegExp("[ ]"), QString::SkipEmptyParts); //去掉 , SkipEmptyParts表示如果末尾为 则不需要打印 foreach (QString line, list) { qDebug()<<line; } } void Widget::sendSerialData() { //serialport.write(QString("%1 ").arg(qrand()).toLocal8Bit()); serialport.write(fromUtf8toGBK(QString("%1 ").arg(qrand()))); } QString Widget::fromGBKtoUtf8(QByteArray arry) { QTextCodec *gbk = QTextCodec::codecForName("gbk"); QTextCodec *utf8 = QTextCodec::codecForName("UTF-8"); QString unicode=gbk->toUnicode(arry); return QString(utf8->fromUnicode(unicode)); } QByteArray Widget::fromUtf8toGBK(QString str) { QTextCodec *gbk = QTextCodec::codecForName("gbk"); QTextCodec *utf8 = QTextCodec::codecForName("UTF-8"); QString unicode=utf8->toUnicode(str.toLocal8Bit()); return gbk->fromUnicode(unicode); }
运行打印:
6.在QThread线程中使用QSerialPort
由于在QThread线程里不能用槽函数,不过可以在run里使用QSerialPort::waitForReadyRead()来阻塞获取读数据.如果在指定时间内读取成功/失败,则向界面发送数据.
示例如下:
serialport.write( QString("%1 ").arg(qrand()).toLocal8Bit() ); //写入随机值 if(serialport.waitForBytesWritten(100)) //100ms 等待写入成功 { if(serialport.waitForReadyRead(100)) //等待数据返回 { QString str((serialport.readAll())); QStringList list = str.split(QRegExp("[ ]"),QString::SkipEmptyParts); //去掉 foreach (QString line, list) { qDebug()<<line; //解析line,并向界面发送信号 ... ... } } else qDebug()<<"read err"; } else qDebug()<<"write err";