Qt制作一个简单通信程序
下面是一个使用Qt的QSerialPort类创建简单串口通信程序的示例。这个程序包含基本的串口配置、数据发送和接收功能。
代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass QSerialPort;#pragma pack(1)
struct TranData
{ushort heard;uint len;char data[0];
};
#pragma pop()class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_open_clicked();void setCtrlEnabled(bool enabled);void on_pushButton_close_clicked();void on_pushButton_send_clicked();QByteArray serializeData(const QByteArray &ba);private:Ui::MainWindow *ui;QSerialPort *m_serial;bool m_bOpen{false};QByteArray recvData;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QThread>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->pushButton_close->setEnabled(false);foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){QSerialPort serial;serial.setPort(info);if(serial.open(QIODevice::ReadWrite)){ui->serialPortName_comboBox->addItem(serial.portName());serial.close();qDebug() << serial.portName();}}//设置波特率下拉菜单默认显示第0项ui->serialPortName_comboBox->setCurrentIndex(0);
}MainWindow::~MainWindow()
{if(m_serial != nullptr && m_serial->isOpen()){m_serial->close();delete m_serial;m_serial = nullptr;}delete ui;
}void MainWindow::on_pushButton_open_clicked()
{m_serial = new QSerialPort(this);m_serial->setPortName(ui->serialPortName_comboBox->currentText()); // 设置串口名m_serial->setBaudRate(ui->serialPort_baudRate->currentText().toInt()); // 设置波特率m_serial->setDataBits((QSerialPort::DataBits)ui->serialPort_dataBit->currentText().toInt()); // 设置数据位m_serial->setParity((QSerialPort::Parity)ui->serialPort_checkBit->currentIndex()); // 设置校验位m_serial->setStopBits((QSerialPort::StopBits)ui->serialPort_stopBit->currentText().toInt()); // 设置停止位// m_serial->setFlowControl(QSerialPort::NoFlowControl); // 设置流控制if (m_serial->open(QIODevice::ReadWrite)){setCtrlEnabled(false);ui->textEdit->append("打开串口成功!");m_bOpen = true;//暂时放这里处理接收信息auto funcRecvData = [&](){while (m_bOpen){QByteArray ba = m_serial->readAll();if(ba.size() > 0){recvData.append(ba);while (recvData.size() > sizeof(TranData)){TranData tData;memcpy(&tData, recvData.data(), sizeof(TranData));if(tData.heard != 0xACFF){recvData.remove(0, 1);}else{if(recvData.size() >= tData.len + sizeof(TranData)){QByteArray buf = recvData.mid(sizeof(TranData), tData.len);;ui->textEdit->append(buf);recvData.remove(0, tData.len + sizeof(TranData));}}}}QThread::msleep(10);}};std::thread t(funcRecvData);t.detach();} else {ui->textEdit->append("打开串口失败!");}
}void MainWindow::setCtrlEnabled(bool enabled)
{ui->serialPortName_comboBox->setEnabled(enabled);ui->serialPort_baudRate->setEnabled(enabled);ui->serialPort_dataBit->setEnabled(enabled);ui->serialPort_checkBit->setEnabled(enabled);ui->serialPort_stopBit->setEnabled(enabled);ui->pushButton_open->setEnabled(enabled);ui->pushButton_close->setEnabled(!enabled);
}void MainWindow::on_pushButton_close_clicked()
{if(m_serial->isOpen()){m_serial->close();if(!m_serial->isOpen()){m_bOpen = false;setCtrlEnabled(true);ui->textEdit->append("关闭串口成功!");}}
}void MainWindow::on_pushButton_send_clicked()
{if(m_serial != nullptr && !m_serial->isOpen()){ui->textEdit->append("串口未打开!");return ;}QString str = ui->lineEdit->text();QByteArray buf = serializeData(str.toUtf8());const int chunkSize = 1024;for (int i = 0; i < buf.size(); i += chunkSize){QByteArray data = buf.mid(i, chunkSize);m_serial->write(data);if (m_serial->waitForBytesWritten()) { // 超时时间 1000msqDebug() << "Data send successfully:" << data;} else {qDebug() << "Failed to send data!";}}
}QByteArray MainWindow::serializeData(const QByteArray &ba)
{const uint16_t HEADER = 0xACFF;const uint32_t dataLen = ba.size();const size_t totalSize = sizeof(TranData) + dataLen;QByteArray buf(totalSize, '\0'); // 预分配足够空间TranData* tData = reinterpret_cast<TranData*>(buf.data());tData->heard = HEADER;tData->len = dataLen;if (dataLen > 0) {memcpy(tData->data, ba.constData(), dataLen);}return buf;
}
.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>762</width><height>460</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QPushButton" name="pushButton_open"><property name="geometry"><rect><x>10</x><y>240</y><width>91</width><height>23</height></rect></property><property name="text"><string>打开</string></property></widget><widget class="QPushButton" name="pushButton_close"><property name="geometry"><rect><x>114</x><y>240</y><width>91</width><height>23</height></rect></property><property name="text"><string>关闭</string></property></widget><widget class="QTextEdit" name="textEdit"><property name="geometry"><rect><x>220</x><y>10</y><width>531</width><height>391</height></rect></property></widget><widget class="QLineEdit" name="lineEdit"><property name="geometry"><rect><x>220</x><y>410</y><width>441</width><height>21</height></rect></property></widget><widget class="QPushButton" name="pushButton_send"><property name="geometry"><rect><x>670</x><y>410</y><width>75</width><height>23</height></rect></property><property name="text"><string>发送</string></property></widget><widget class="QWidget" name="layoutWidget"><property name="geometry"><rect><x>10</x><y>20</y><width>191</width><height>211</height></rect></property><layout class="QVBoxLayout" name="verticalLayout"><item><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QLabel" name="label"><property name="text"><string>串口号:</string></property></widget></item><item><widget class="QComboBox" name="serialPortName_comboBox"><property name="minimumSize"><size><width>120</width><height>25</height></size></property></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_2"><item><widget class="QLabel" name="label_2"><property name="text"><string>波特率:</string></property></widget></item><item><widget class="QComboBox" name="serialPort_baudRate"><property name="minimumSize"><size><width>120</width><height>25</height></size></property><property name="currentIndex"><number>3</number></property><item><property name="text"><string>1200</string></property></item><item><property name="text"><string>2400</string></property></item><item><property name="text"><string>4800</string></property></item><item><property name="text"><string>9600</string></property></item><item><property name="text"><string>19200</string></property></item><item><property name="text"><string>38400</string></property></item><item><property name="text"><string>115200</string></property></item></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_3"><item><widget class="QLabel" name="label_3"><property name="text"><string>数据位:</string></property></widget></item><item><widget class="QComboBox" name="serialPort_dataBit"><property name="minimumSize"><size><width>120</width><height>25</height></size></property><property name="currentIndex"><number>3</number></property><item><property name="text"><string>5</string></property></item><item><property name="text"><string>6</string></property></item><item><property name="text"><string>7</string></property></item><item><property name="text"><string>8</string></property></item></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_6"><item><widget class="QLabel" name="label_6"><property name="text"><string>校验位:</string></property></widget></item><item><widget class="QComboBox" name="serialPort_checkBit"><property name="minimumSize"><size><width>120</width><height>25</height></size></property><item><property name="text"><string>None</string></property></item><item><property name="text"><string>Even</string></property></item><item><property name="text"><string>Odd</string></property></item><item><property name="text"><string>Space</string></property></item><item><property name="text"><string>Mark</string></property></item></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_5"><item><widget class="QLabel" name="label_5"><property name="text"><string>停止位:</string></property></widget></item><item><widget class="QComboBox" name="serialPort_stopBit"><property name="minimumSize"><size><width>120</width><height>25</height></size></property><item><property name="text"><string>1</string></property></item><item><property name="text"><string>3</string></property></item><item><property name="text"><string>2</string></property></item></widget></item></layout></item></layout></widget></widget><widget class="QMenuBar" name="menubar"><property name="geometry"><rect><x>0</x><y>0</y><width>762</width><height>21</height></rect></property></widget></widget><resources/><connections/>
</ui>
main.cpp
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
.pro记得加上 QT += serialport
程序说明
串口初始化:
创建QSerialPort对象
连接readyRead信号到读取数据的槽函数
连接errorOccurred信号到错误处理槽函数
串口配置:
设置端口名称、波特率、数据位、校验位、停止位和流控制
支持常见的串口参数配置
主要功能:
openSerialPort()
: 打开并配置串口closeSerialPort()
: 关闭串口writeData()
: 发送数据readData()
: 接收数据handleError()
: 错误处理
使用示例:
列出所有可用串口
打开指定串口
发送测试数据"Hello, Serial Port!"