目录
前言
本篇记录QT串口编程相关内容,并制作一个串口助手来巩固理论知识。
一、串口编程步骤
0. 添加串口模块
pro文件中QT += serialport
1. 自动搜索已连接的串口
假设我们已经在ui设计器里添加了一个QComboBox的对象cbSerialPort。接下来,我们通过以下代码将所有已连接的串口名称加入cbSerialPort中,方便用户选择。
//QSerialPortInfo::availablePorts()能够自动搜索已连接的串口
//需要添加头文件<QSerialPortInfo>
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cbSerialPort->addItem(info.portName());
}
2. 创建串口对象
//需要添加头文件<QSerialPort>
QSerialPort * serialport = new QSerialPort(this);
3. 初始化串口
【1】初始化串口名:
serialPort->setPortName(ui->cbSerialPort->currentText());
【2】初始化波特率:
QSerialPort::BaudRate baudRate;
if (ui->cbBaudRate->currentText() == "4800") {
baudRate = QSerialPort::Baud4800;
} else if (ui->cbBaudRate->currentText() == "9600") {
baudRate = QSerialPort::Baud9600;
} else if (ui->cbBaudRate->currentText() == "115200") {
baudRate = QSerialPort::Baud115200;
}
serialPort->setBaudRate(baudRate);
【3】初始化数据位:
QSerialPort::DataBits dataBits;
if (ui->cbDataBit->currentText() == "5") {
dataBits = QSerialPort::Data5;
} else if (ui->cbDataBit->currentText() == "6") {
dataBits = QSerialPort::Data6;
} else if (ui->cbDataBit->currentText() == "7") {
dataBits = QSerialPort::Data7;
} else if (ui->cbDataBit->currentText() == "8") {
dataBits = QSerialPort::Data8;
}
serialPort->setDataBits(dataBits);
【4】初始化停止位:
QSerialPort::StopBits stopBits;
if (ui->cbStopBit->currentText() == "1") {
stopBits = QSerialPort::OneStop;
} else if (ui->cbStopBit->currentText() == "1.5") {
stopBits = QSerialPort::OneAndHalfStop;
} else if (ui->cbStopBit->currentText() == "2") {
stopBits = QSerialPort::TwoStop;
}
serialPort->setStopBits(stopBits);
【5】初始化校验位:
QSerialPort::Parity parity;
if (ui->cbCheckBit->currentText() == "none") {
parity = QSerialPort::NoParity;
}
serialPort->setParity(parity);
4. 打开串口
//弹出一个窗口告知用户初始化结果
if (serialPort->open(QIODevice::ReadWrite)) {
QMessageBox::information(this, "提示", "成功");
} else {
QMessageBox::critical(this, "提示", "失败");
}
5. 关闭串口
serialPort->close();
6. 发送数据
serialPort->write(ui->sendEdit->text().toUtf8());
7. 接收数据
【1】建立信号槽,当有数据发送过来时,调用自定义的槽函数receiveMessage()
connect(serialPort, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
【2】实现槽函数receiveMessage()
void Widget::receiveMessage()
{
QString buf = serialPort->readAll();
ui->recvEdit->appendPlainText(buf);
}
二、简易串口助手
1. 实现效果
此QT程序在Windows环境下编译运行,且连接IMX6ULL开发板(串口号为12)。IMX6ULL开发板收到信息后会自动发回接收到的信息。因此,本程序的实现效果如下图所示:
2. 程序源码
【1】widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSerialPort>
#include <QSerialPortInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btnOpenSerial_clicked();
void on_btnCloseSerial_clicked();
void receiveMessage();
void on_btnSendMesg_clicked();
void on_btnClearRecv_clicked();
void on_btnClearSend_clicked();
private:
Ui::Widget *ui;
QSerialPort *serialPort;
};
#endif // WIDGET_H
【2】widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
/***********************************************************
* @函数: Widget
* @功能: 构造函数
* @参数: parent---父对象
* @返回: 无
*********************************************************/
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//搜索连接的串口,将名称加入cbSerialPort中
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cbSerialPort->addItem(info.portName());
}
//创建串口对象
serialPort = new QSerialPort(this);
//信号槽:串口接收数据
connect(serialPort, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
//设置"打开串口"与"关闭串口"按钮互斥
ui->btnOpenSerial->setEnabled(true);
ui->btnCloseSerial->setEnabled(false);
}
/***********************************************************
* @函数: ~Widget
* @功能: 析构函数
* @参数: 无
* @返回: 无
*********************************************************/
Widget::~Widget()
{
delete ui;
}
/***********************************************************
* @函数: on_btnOpenSerial_clicked
* @功能: “打开串口”按钮的槽函数,初始化串口
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::on_btnOpenSerial_clicked()
{
//初始化串口名
serialPort->setPortName(ui->cbSerialPort->currentText());
//初始化波特率
QSerialPort::BaudRate baudRate;
if (ui->cbBaudRate->currentText() == "4800") {
baudRate = QSerialPort::Baud4800;
} else if (ui->cbBaudRate->currentText() == "9600") {
baudRate = QSerialPort::Baud9600;
} else {
baudRate = QSerialPort::Baud115200;
}
serialPort->setBaudRate(baudRate);
//初始化数据位
QSerialPort::DataBits dataBits;
if (ui->cbDataBit->currentText() == "5") {
dataBits = QSerialPort::Data5;
} else if (ui->cbDataBit->currentText() == "6") {
dataBits = QSerialPort::Data6;
} else if (ui->cbDataBit->currentText() == "7") {
dataBits = QSerialPort::Data7;
} else {
dataBits = QSerialPort::Data8;
}
serialPort->setDataBits(dataBits);
//初始化停止位
QSerialPort::StopBits stopBits;
if (ui->cbStopBit->currentText() == "1") {
stopBits = QSerialPort::OneStop;
} else if (ui->cbStopBit->currentText() == "1.5") {
stopBits = QSerialPort::OneAndHalfStop;
} else {
stopBits = QSerialPort::TwoStop;
}
serialPort->setStopBits(stopBits);
//初始化校验位
QSerialPort::Parity parity;
if (ui->cbCheckBit->currentText() == "none") {
parity = QSerialPort::NoParity;
}
serialPort->setParity(parity);
//弹出一个窗口告知用户初始化结果
if (serialPort->open(QIODevice::ReadWrite)) {
QMessageBox::information(this, "提示", "串口打开成功");
//设置"打开串口"与"关闭串口"按钮互斥
ui->btnOpenSerial->setEnabled(false);
ui->btnCloseSerial->setEnabled(true);
} else {
QMessageBox::critical(this, "提示", "串口打开失败");
}
}
/***********************************************************
* @函数: on_btnCloseSerial_clicked
* @功能: “关闭串口”按钮的槽函数
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::on_btnCloseSerial_clicked()
{
serialPort->close();
//设置"打开串口"与"关闭串口"按钮互斥
ui->btnOpenSerial->setEnabled(true);
ui->btnCloseSerial->setEnabled(false);
}
/***********************************************************
* @函数: receiveMessage
* @功能: 槽函数:接收信息
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::receiveMessage()
{
QString buf = serialPort->readAll();
ui->recvEdit->appendPlainText(buf);
}
/***********************************************************
* @函数: on_btnSendMesg_clicked
* @功能: “发送信息”按钮的槽函数
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::on_btnSendMesg_clicked()
{
serialPort->write(ui->sendEdit->text().toUtf8());
}
/***********************************************************
* @函数: on_btnClearRecv_clicked
* @功能: “清除接收框”按钮的槽函数
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::on_btnClearRecv_clicked()
{
ui->recvEdit->clear();
}
/***********************************************************
* @函数: on_btnClearSend_clicked
* @功能: “清除输入框”按钮的槽函数
* @参数: 无
* @返回: 无
*********************************************************/
void Widget::on_btnClearSend_clicked()
{
ui->sendEdit->clear();
}
3. 实现效果二
【1】为了进一步验证简易串口助手的功能,我们进行了如下的实验。
【2】首先,根据视频【虚拟串口创建工具】虚拟串口软件安装教程_哔哩哔哩_bilibili,我们安装了虚拟串口软件,并且产生了两个虚拟串口,如下图所示:
【3】其次,我们开发的串口助手连接com2,另一个串口工具连接com1。如下图所示,它们能够正常地收发数据,这再一次说明了我们开发的串口助手功能是正常的。