第六章 QT基础:2、编程基础及串口助手案例
一、QT下的三驾马车
1、QT的串口编程
QT的串口编程使用QtSerialPort模块,它提供了对串口设备的支持,使得应用程序能够方便地与硬件设备通过串口进行通信。串口编程常用于设备通信、数据采集等领域。
- 初始化串口: 使用 QSerialPort 类来创建串口对象,设置串口的基本属性,如波特率、数据位、停止位等。
QSerialPort *serial = new QSerialPort(this);
serial->setPortName("COM1"); // 设置串口名称
serial->setBaudRate(QSerialPort::Baud9600); // 设置波特率
serial->setDataBits(QSerialPort::Data8); // 数据位
serial->setParity(QSerialPort::NoParity); // 校验位
serial->setStopBits(QSerialPort::OneStop); // 停止位
- 打开串口:
if (serial->open(QIODevice::ReadWrite)) {qDebug() << "串口打开成功!";
} else {qDebug() << "串口打开失败!";
}
- 数据发送与接收: 发送数据可以通过 write() 方法,接收数据可以使用 readyRead() 信号来监听。
serial->write("Hello, Serial Port!"); // 发送数据
connect(serial, &QSerialPort::readyRead, this, &MainWindow::onReadyRead);
- 数据接收方法:
void MainWindow::onReadyRead() {QByteArray data = serial->readAll(); // 读取串口数据qDebug() << data;
}
2、QT下的网络编程
QT支持多种网络协议的编程,主要使用 QTcpSocket 和 QTcpServer 类来进行TCP协议的编程。
- 客户端网络编程: 使用 QTcpSocket 类来创建客户端与服务器进行通信。
QTcpSocket *socket = new QTcpSocket(this);
socket->connectToHost("localhost", 1234); // 连接到服务器
socket->write("Hello, Server!"); // 发送数据
- 服务器端编程: 使用 QTcpServer 类来创建一个简单的服务器。
QTcpServer *server = new QTcpServer(this);
if (server->listen(QHostAddress::Any, 1234)) {qDebug() << "服务器已启动!";
} else {qDebug() << "服务器启动失败!";
}connect(server, &QTcpServer::newConnection, this, &MainWindow::onNewConnection);
客户端连接到服务器后,接收到的连接可以通过 newConnection 信号来处理。
3、QT下的GPIO
在QT中,GPIO(通用输入输出)通常通过操作底层硬件接口来进行控制,例如通过/dev/下的文件进行输入输出。在QT中并没有直接的GPIO模块,因此通常需要借助底层操作系统的接口进行GPIO编程。
二、仿写串口助手
步骤一:做好UI界面
仿写串口助手的第一步是创建一个界面,界面通常包括以下组件:
-
接收框:显示从串口接收到的数据
![[Pasted image 20250415110752.png]] -
发送框:用户输入要发送的数据
![[Pasted image 20250415110823.png]] -
发送按钮:点击后将发送框中的数据发送出去
-
串口配置区:包括串口号选择、波特率选择、数据位选择、校验位选择、停止位选择等
-
打开/关闭串口按钮:用于打开或关闭串口
步骤二:实现串口操作功能
- 打开串口:
void MainWindow::on_OpenButton_clicked() {QString portName = ui->comboBoxPortName->currentText();int baudRate = ui->comboBoxBaudRate->currentText().toInt();QString dataBits = ui->comboBoxDataBits->currentText();QString parity = ui->comboBoxParity->currentText();QString stopBits = ui->comboBoxStopBits->currentText();serial->setPortName(portName);serial->setBaudRate(baudRate);// 设置其他串口参数...if (serial->open(QIODevice::ReadWrite)) {ui->OpenButton->setText("关闭");qDebug() << "串口打开成功!";} else {qDebug() << "串口打开失败!";}
}
- 关闭串口:
void MainWindow::on_CloseButton_clicked() {serial->close();ui->OpenButton->setText("打开");qDebug() << "串口已关闭!";
}
- 发送数据:
void MainWindow::on_SendButton_clicked() {QString data = ui->SendTextEdit->toPlainText();serial->write(data.toUtf8());qDebug() << "发送数据: " << data;
}
- 接收数据:
void MainWindow::onReadyRead() {QByteArray data = serial->readAll();ui->ReceiveTextEdit->append(data);qDebug() << "接收到数据: " << data;
}
步骤三:实现其他功能
- 自动换行:在接收框中实现自动换行功能,方便查看数据
- 清空接收框:添加一个按钮,点击后清空接收框中的内容
- 保存接收数据:将接收的数据保存到文件中
- 打开串口时的错误处理:处理打开串口时可能出现的各种错误
串口代码案例:
#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QString>
#include <QMessageBox>// 构造函数:初始化 UI 和串口设置
Widget::Widget(QWidget *parent) :QWidget(parent), // 调用 QWidget 构造函数ui(new Ui::Widget) // 初始化 UI 对象
{ui->setupUi(this); // 设置 UI 界面QStringList serialNamePort; // 创建一个字符串列表,用于存储串口名称serialPort = new QSerialPort(this); // 创建 QSerialPort 对象,用于串口通信// 连接串口的 readyRead 信号到槽函数 serialPortReadyRead_slotconnect(serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead_slot()));// 遍历可用的串口,并将串口名称添加到 combobox 中foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {serialNamePort << info.portName(); // 将串口名称加入列表ui->serialCb->addItems(serialNamePort); // 将串口名称添加到界面上的 comboBox 中}
}// 析构函数:清理内存
Widget::~Widget()
{delete ui; // 删除 UI 对象,释放内存
}// 串口数据读取槽函数:每次串口有数据时被调用
void Widget::serialPortReadyRead_slot()
{QString buf; // 创建字符串变量,用于存储接收到的数据buf = QString(serialPort->readAll()); // 读取串口的所有数据并转换为 QString 格式ui->recvEdit->appendPlainText(buf); // 将接收到的数据添加到界面上的接收框中
}// 打开串口按钮的点击事件
void Widget::on_OpenBt_clicked()
{QSerialPort::BaudRate bauRates; // 声明变量,用于存储波特率QSerialPort::DataBits dataBits; // 声明变量,用于存储数据位QSerialPort::StopBits stopBits; // 声明变量,用于存储停止位QSerialPort::Parity checkBits; // 声明变量,用于存储校验位// 根据 combobox 中选择的波特率设置 bauRatesif(ui->baundrateCb->currentText() == "4800"){bauRates = QSerialPort::Baud4800;}else if(ui->baundrateCb->currentText() == "9600") {bauRates = QSerialPort::Baud9600;}else if(ui->baundrateCb->currentText() == "115200") {bauRates = QSerialPort::Baud115200;}// 根据 combobox 中选择的数据位设置 dataBitsif(ui->dataCb->currentText() == "5") {dataBits = QSerialPort::Data5;}else if(ui->dataCb->currentText() == "6") {dataBits = QSerialPort::Data6;}else if(ui->dataCb->currentText() == "7") {dataBits = QSerialPort::Data7;} else if(ui->dataCb->currentText() == "8") {dataBits = QSerialPort::Data8;}// 根据 combobox 中选择的停止位设置 stopBitsif(ui->stopCb->currentText() == "1") {stopBits = QSerialPort::OneStop;} else if(ui->stopCb->currentText() == "1.5") {stopBits = QSerialPort::OneAndHalfStop;} else if(ui->stopCb->currentText() == "2") {stopBits = QSerialPort::TwoStop;}// 根据 combobox 中选择的校验位设置 checkBitsif(ui->checkCb->currentText() == "none") {checkBits = QSerialPort::NoParity;}// 设置串口的各种属性serialPort->setPortName(ui->serialCb->currentText()); // 设置串口名称serialPort->setBaudRate(bauRates); // 设置波特率serialPort->setDataBits(dataBits); // 设置数据位serialPort->setStopBits(stopBits); // 设置停止位serialPort->setParity(checkBits); // 设置校验位// 打开串口,如果成功则弹出提示框if(serialPort->open(QIODevice::ReadWrite)) {QMessageBox::information(this, "提示", "成功打开串口"); // 打开成功,弹出提示框} else {QMessageBox::critical(this, "错误", "无法打开串口"); // 打开失败,弹出错误框}
}// 关闭串口按钮的点击事件
void Widget::on_CloseBt_clicked()
{serialPort->close(); // 关闭串口
}// 发送数据按钮的点击事件
void Widget::on_SendBt_clicked()
{// 获取文本框中的内容并发送到串口serialPort->write(ui->sendEdit->text().toLocal8Bit().data());
}// 清空接收区按钮的点击事件
void Widget::on_ClearBt_clicked()
{ui->recvEdit->clear(); // 清空接收框中的内容
}// 串口回车换行按钮的点击事件
void Widget::on_checkBox_stateChanged(int arg1)
{QString a = "\r\n"; // 定义回车换行字符serialPort->write(a.toLocal8Bit().data()); // 向串口发送回车换行字符
}