目录
3.1 RS485接口的Modbus Poll 持续发送串口数据
4.2【QT】串口助手(优化升级 详细注解) qt5_serial.zip
1 串口助手最终成品效果
1.1 串口功能描述
检测当前可用的通讯端口,如COM1、COM2、COM3、COM4等
配置端口号、波特率、数据位、校验位、停止位参数
串口当前状态,连接(打开)还是未连接(关闭)
发送默认是ASCII格式发送,可配置HEX 16进制格式,还有自动发送功能
接收默认是ASCII格式发送,可配置HEX 16进制格式,还有自动换行、显示接收时间功能
具有打开端口open、停止端口close、清空接收clear等功能
1.2 串口接收数据显示图
启动嵌入式Linux系统串口接收显示数据界面
1.3 串口发送数据显示图
输入 ifconfig 命令查看IP地址等信息界面
2 项目编程代码详解
2.1 项目框架
2.2 工程配置 serial.pro
注意:添加serialport,即 QT += core gui serialport
- QT += core gui serialport
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # The following define makes your compiler emit warnings if you use
- # any Qt feature that has been marked deprecated (the exact warnings
- # depend on your compiler). Please consult the documentation of the
- # deprecated API in order to know how to port your code away from it.
- DEFINES += QT_DEPRECATED_WARNINGS
-
- # You can also make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- # You can also select to disable deprecated APIs only up to a certain version of Qt.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- serial.cpp
-
- HEADERS += \
- serial.h
-
- FORMS += \
- serial.ui
-
- RC_ICONS = system.ico
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
2.3 设计布局 serial.ui
2.4 串口头文件 serial.h (包含详细注释)
- #ifndef SERIAL_H
- #define SERIAL_H
-
- #include <QMainWindow>
-
- /*-------------user-------------------*/
- /*---port--*/
- #include <QSerialPort>
- #include <QSerialPortInfo>
- /*---QString--*/
- #include <QString>
- /*---QDateTime--*/
- #include <QDateTime>
- /*---QTimer--*/
- #include <QTimer>
- /*---QDebug--*/
- #include <QDebug>
- #define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"
- /* -----------------------------------*/
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Serial; }
- QT_END_NAMESPACE
-
- class Serial : public QMainWindow
- {
- Q_OBJECT
-
- public:
- Serial(QWidget *parent = nullptr);
- ~Serial();
-
- signals: //自定义信号
- //发送使能信号
- void my_send_signals(bool);
-
- private slots: //自定义槽函数
- //检测通讯端口槽函数
- void btn_serial_check(bool);
- //打开选择端口槽函数
- void btn_open_port(bool);
- //关闭选择端口槽函数
- void btn_close_port(bool);
- //发送数据槽函数
- void btn_send_data(bool);
- //接收数据槽函数
- void receive_data(void);
- //清空接收槽函数
- void btn_clear_rev(bool);
-
- //自动发送复选框槽函数
- void on_checkBox_stateChanged(int arg1);
-
- private:
- Ui::Serial *ui;
- /*--------funtion---------------------*/
- //用户系统初始化
- void system_init();
- //字符串转16进制
- QByteArray QString2Hex(QString str);
- //字符转16进制
- char ConvertHexChar(char ch);
- /*--------variable--------------------*/
- //串口全局类声明
- QSerialPort global_port;
- //自动发送定时器声明
- QTimer *timer;
- };
- #endif // SERIAL_H
2.5 串口源代码 serial.cpp(包含详细注释)
- #include "serial.h"
- #include "ui_serial.h"
-
- Serial::Serial(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::Serial)
- {
- ui->setupUi(this);
-
- /*----------user-----------*/
- //init 用户系统初始化
- system_init();
- }
-
- Serial::~Serial()
- {
- delete ui;
- }
-
- /*---------------------------------------------------------------------
- * funtion
- * --------------------------------------------------------------------*/
- //用户系统初始化
- void Serial::system_init()
- {
- //port conifg
- ui->cmd_port_name->clear();
- //通过QSerialPortInfo查找可用串口
- foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
- {
- //将可用串口添加到端口显示框
- ui->cmd_port_name->addItem(info.portName());
- }
-
- //设置串口状态标签为红色 表示未连接状态
- ui->lab_status->setStyleSheet("color:red");
- //statusBar 状态栏显示端口状态 未连接
- QString sm = "%1 CLOSED";
- QString status = sm.arg(ui->cmd_port_name->currentText());
- ui->statusBar->showMessage(status);
- ui->statusBar->setStyleSheet("color:red");
-
- //timer 自动发送
- timer = new QTimer(this);
- connect(timer,&QTimer::timeout,[=](){
- emit my_send_signals(true); //触发发送信号
- });
-
-
- //connect
- //check port 检测通讯端口
- connect(ui->btn_serial,&QPushButton::clicked,this,&Serial::btn_serial_check);
- //open port 打开选择端口
- connect(ui->btn_open,&QPushButton::clicked,this,&Serial::btn_open_port);
- //close port 关闭选择端口
- connect(ui->btn_close,&QPushButton::clicked,this,&Serial::btn_close_port);
-
- //send data 发送按钮 触发发送信号
- connect(ui->btn_send,&QPushButton::clicked,[=](){
- emit my_send_signals(true);
- });
- //发送信号 发送槽函数
- connect(this,&Serial::my_send_signals,this,&Serial::btn_send_data);
-
- //receive data 串口数据接收完触发更新添加显示接收文本框
- connect(&global_port,&QSerialPort::readyRead,this,&Serial::receive_data);
- //clear recevie 清除接收文本框的内容
- connect(ui->btn_clear,&QPushButton::clicked,this,&Serial::btn_clear_rev);
-
- }
-
- //字符串转16进制
- QByteArray Serial::QString2Hex(QString str)
- {
- QByteArray senddata;
- int hexdata,lowhexdata;
- int hexdatalen = 0;
- int len = str.length();
-
- senddata.resize(len/2);
- char lstr,hstr;
-
- for(int i=0; i<len; )
- {
- hstr=str[i].toLatin1();
- if(hstr == ' ')
- {
- i++;
- continue;
- }
- i++;
- if(i >= len)
- break;
- lstr = str[i].toLatin1();
- hexdata = ConvertHexChar(hstr);
- lowhexdata = ConvertHexChar(lstr);
- if((hexdata == 16) || (lowhexdata == 16))
- break;
- else
- hexdata = hexdata*16+lowhexdata;
- i++;
- senddata[hexdatalen] = (char)hexdata;
- hexdatalen++;
- }
- senddata.resize(hexdatalen);
- return senddata;
- }
- //字符转16进制
- char Serial::ConvertHexChar(char ch)
- {
- if((ch >= '0') && (ch <= '9'))
- return ch-0x30;
- else if((ch >= 'A') && (ch <= 'F'))
- return ch-'A'+10;
- else if((ch >= 'a') && (ch <= 'f'))
- return ch-'a'+10;
- else return (-1);
- }
-
- /*---------------------------------------------------------------------
- * slots
- * --------------------------------------------------------------------*/
- //检测通讯端口槽函数
- void Serial::btn_serial_check(bool)
- {
- ui->cmd_port_name->clear();
- //通过QSerialPortInfo查找可用串口
- foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
- {
- ui->cmd_port_name->addItem(info.portName());
- }
- }
-
- //打开选择端口槽函数
- void Serial::btn_open_port(bool)
- {
- //port name 设置端口
- global_port.setPortName(ui->cmd_port_name->currentText());
- //baud rate 设置波特率
- global_port.setBaudRate(ui->cmd_baud_rate->currentText().toInt());
- //parity 设置校验位
- switch (ui->cmd_parity->currentIndex()) {
- case 0: //无校验
- global_port.setParity(QSerialPort::NoParity);
- break;
- case 1: //偶校验
- global_port.setParity(QSerialPort::EvenParity);
- break;
- default: //奇校验
- global_port.setParity(QSerialPort::OddParity);
- break;
- }
-
- //data bits 设置数据位
- switch (ui->cmd_data_bits->currentText().toInt()) {
- case 8:
- global_port.setDataBits(QSerialPort::Data8);
- break;
- case 7:
- global_port.setDataBits(QSerialPort::Data7);
- break;
- case 6:
- global_port.setDataBits(QSerialPort::Data6);
- break;
- default:
- global_port.setDataBits(QSerialPort::Data5);
- break;
- }
-
- //stop bits 设置停止位
- switch (ui->cmd_stop_bits->currentIndex()) {
- case 0:
- global_port.setStopBits(QSerialPort::OneStop);
- break;
- case 1:
- global_port.setStopBits(QSerialPort::OneAndHalfStop);
- break;
- default:
- global_port.setStopBits(QSerialPort::TwoStop);
- break;
- }
-
- //port open 打开选择端口
- bool ret = global_port.open(QIODevice::ReadWrite);
-
- if(ret){
- //打开成功更新状态
- ui->lab_status->setText("Connected");
- //设置串口状态标签为绿色 表示已连接状态
- ui->lab_status->setStyleSheet("color:green");
-
- //statusBar 状态栏显示端口状态
- QString sm = "%1 OPENED, %2, 8, NONE, 1";
- QString status = sm.arg(global_port.portName()).arg(global_port.baudRate());
- ui->statusBar->showMessage(status);
- ui->statusBar->setStyleSheet("color:green");
- }
- }
-
- //关闭选择端口槽函数
- void Serial::btn_close_port(bool)
- {
-
- global_port.close();
-
- //关闭端口后显示状态
- ui->lab_status->setText("DisConnected");
- ui->lab_status->setStyleSheet("color:red");
-
- //statusBar 状态栏显示端口状态
- QString sm = "%1 CLOSED";
- QString status = sm.arg(global_port.portName());
- ui->statusBar->showMessage(status);
- ui->statusBar->setStyleSheet("color:red");
- }
-
- //发送数据槽函数
- void Serial::btn_send_data(bool)
- {
- QString data = ui->pte_send->toPlainText();
- QByteArray array;
-
- //Hex复选框
- if(ui->chk_send_hex->checkState() == Qt::Checked){
- array = QString2Hex(data); //HEX 16进制
- }else{
- array = data.toLatin1(); //ASCII
- }
- global_port.write(array); //发送数据
- }
-
- //接收数据槽函数
- void Serial::receive_data(void)
- {
- QByteArray array = global_port.readAll();
- QString str_rev;
-
- if(ui->chk_rev_hex->checkState() == Qt::Checked){ //HEX 16进制
- if(ui->chk_rev_line->checkState() == Qt::Checked){ //自动换行
- if(ui->chk_rev_time->checkState() == Qt::Checked){ //显示时间
- //获取当前系统时间
- QDateTime nowtime = QDateTime::currentDateTime();
- //时间转换为字符串格式
- str_rev = "[" + nowtime.toString("yyyy-MM-dd hh:mm:ss") + "] ";
- //加上接收数据 转换为16进制并空格分开 接收数据换行
- str_rev += QString(array.toHex(' ').toUpper().append(' ')).append("\r\n");
- }else{
- str_rev = QString(array.toHex(' ').toUpper().append(' ')).append("\r\n");
- }
- }else{
- str_rev = QString(array.toHex(' ').toUpper().append(' '));
- }
-
- }else{
- if(ui->chk_rev_line->checkState() == Qt::Checked){
- if(ui->chk_rev_time->checkState() == Qt::Checked){
- QDateTime nowtime = QDateTime::currentDateTime();
- str_rev = "[" + nowtime.toString("yyyy-MM-dd hh:mm:ss") + "] ";
- str_rev += QString(array).append("\r\n");
- }else{
- str_rev = QString(array).append("\r\n");
- }
- }else{
- str_rev = QString(array);
- }
-
- }
-
- ui->pte_rcv->insertPlainText(str_rev);
- }
-
- //清空接收文本框槽函数
- void Serial::btn_clear_rev(bool)
- {
- ui->pte_rcv->clear();
- }
-
- //自动触发复选框 启动定时器和停止定时器
- void Serial::on_checkBox_stateChanged(int arg1)
- {
- if(arg1){
- timer->start(ui->spinBox->value()); //启动定时器
- }else{
- timer->stop(); //停止定时器
- }
- }
2.6 主函数入口 main.cpp
- #include "serial.h"
-
- #include <QApplication>
-
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Serial w;
- w.show();
- return a.exec();
- }
3 移植到ARM嵌入式Linux开发板
参考移植博文:【ARM嵌入式Linux】正点原子I.MX6U-ALPHA的QT交叉编译环境搭建