801 字
4 分钟
Qt 串口调试
准备
新建项目后,找到 xxx.pro 文件,修改代码如下:
QT += core gui serialport
增加 serialprot 模块用来完成串口调试等功能。
项目的头文件 Headers/xxx.h ,增加如下代码:
#include <QtSerialPort/QtSerialPort>#include <QtSerialPort/QSerialPortInfo>
根据版本不同,导入方式有所不同,具体看 qt 版本 QtSerialPort:提供操作串口的接口 QSerialPortInfo:提供可用串口信息
使用 UI 编辑器,编辑一个界面,大致需求如下:
- ComboBox_Port:显示和选择串口
- ComboBox_Baud::显示和选择串口波特率
- PushButton_RefreshPort:刷新可用串口信息
- PushButton_Login:打开或关闭串口
- LineEdit_SendData_Edit:编辑需要发送信息
- PushButton_SendData::点击后发送 行编辑框 中的信息
基础功能
初始化
在项目头文件中增加成员 mainSerialPort ,用来对串口进行操作:
class Mermaid : public QMainWindow{ ...private: Ui::Mermaid *ui; QSerialPort *mainSerialPort; // 增加代码};#endif // MERMAID_H
初始化串口和波特率的 ComboBox 中的可选项:
代码 - 点击查看详情
Mermaid::Mermaid(QWidget *parent) : QMainWindow(parent) , ui(new Ui::Mermaid){ ... mainSerialPort = new QSerialPort(this); QStringList serialPortList; foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { serialPortList << info.portName(); } ui->comboBox_Port->addItems(serialPortList); ui->comboBox_Baud->addItem({"9600", "115200"});}
功能实现
选择串口后,点击“建立链路”后,打开串口
代码 - 点击查看详情
void Mermaid::on_pushButton_Login_clicked(){ mainSerialPort->setPortName(ui->comboBox_Port->currentText()); mainSerialPort->setBaudRate(ui->comboBox_Baud->currentText().toInt()); mainSerialPort->setDataBits(QSerialPort::Data8); mainSerialPort->setStopBits(QSerialPort::OneStop); mainSerialPort->setParity(QSerialPort::NoParity);
if (ui->pushButton_Login->text().compare("建立链路") == 0) { if (mainSerialPort->open(QIODevice::ReadWrite)) { ui->pushButton_Login->setText("断开链路"); ui->pushButton_Login->setStyleSheet("background-color:green"); } else { QMessageBox::information(this, "提示", "串口打开失败!"); } } else { mainSerialPort->close(); ui->pushButton_Login->setText("建立链路"); ui->pushButton_Login->setStyleSheet("background-color:red"); }}
点击 “更新” ,更新下拉框中的串口信息
本来的想法是找 ComboBox 弹出下拉菜单的方法,在弹出下拉菜单的同时,修改列表内容。但 Qt 并不支持,这里我偷懒通过按钮进行刷新。根据我 PyQt 中的经验,可以通过重写 showPopup() 函数进行实现或者多线程来实现相同效果。
代码 - 点击查看详情
void Mermaid::on_pushButton_RefreshPort_clicked(){ QStringList serialPortList; foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { serialPortList <<info.portName(); } ui->comboBox_Port->clear(); // 清空列表内容 ui->comboBox_Port->addItems(serialPortList); // 更新列表内容}
点击“发送”,让程序通过串口发送信息:
代码 - 点击查看详情
void Mermaid::on_pushButton_SendData_clicked(){ //方法1:write char * 字符串 //QString >> std::string >> char * QString qstr = ui->lineEdit_SendDataEdit->text(); std::string str = qstr.toStdString(); mainSerialPort->write(str.c_str());
//方法2:write QByteArray //QString >> QByteArray QString qstr = ui->lineEdit_SendDataEdit->text(); QByteArray array(qstr); mainSerialPort->write(array);
}
测试硬件
通过 Arduino 简单实现了通过串口读取 “on” 或 “off” 实现开关灯,来验证程序是否正常运行:
代码 - 点击查看详情
void setup(){ Serial.begin(9600); pinMode(13, OUTPUT); digitalWrite(13, LOW);}
String strCmd = "";
void loop(){ while (Serial.available()){ strCmd += char(Serial.read()); delay(2); } if (strCmd == "on") digitalWrite(13, HIGH); if (strCmd == "off") digitalWrite(13, LOW); if (strCmd.length() > 0) Serial.println(strCmd); strCmd = "";}
读取数据
多线程定时读取
- 通过 QThread 创建线程
- 线程内部通过串口类读取,或发射信号到主窗口,由主窗口读取
readyRead 信号
- 创建 receiveData() 函数用于读取串口数据
- 将 QSerialPort 的 readyRead 信号与接收函数连接
QSerialPort *device = new QSerialPort();QObject::connect(device, &QSerialPort::readyRead, this, &MainWindow::receiveData);
void MainWindow::receiveData(){ QByteArray byteArray = device->readAll(); qDebug << byteArray.data();}
QByteArray::data()
- 将字节数据转换成 char * 字符串
QByteArray::toHexo(char separator = ‘\0’)
- 将字节数据转换成 HEX 编码的 char * 字符串
- 每个字节间通过 separator 符号分割