801 字
4 分钟
Qt 串口调试
2022-01-21

准备#

新建项目后,找到 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() 函数用于读取串口数据
  • QSerialPortreadyRead 信号与接收函数连接
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 符号分割
Qt 串口调试
https://fuwari.vercel.app/posts/编程/qt/qt-串口调试/
作者
Asuwee
发布于
2022-01-21
许可协议
CC BY-NC-SA 4.0