当前位置: 首页 > news >正文

QT:串口通信、串口发送与接收(2)

使用版本为 Qt 5.9.8(Qt 5.1以上 6 以下的版本都适用)

目录

一、效果演示

二、UI界面

三、完整代码

(1).pro

(2)mainwindow.h

(3)mainwindow.cpp    

(4)main.cpp    


         最近用到Qt做串口通信上位机,翻看了之前写过一篇文章,写的有点乱(传送门),于是打算重新整理一个完整的串口通信上位机的模板工程,功能和之前的一样,代码部分也不再详细介绍,都有详细注释。附完整代码和工程文件资源。

一、效果演示

        用的虚拟串口COM1、COM2模拟串口通信。右边为QT设计的串口工具,左边为XCOM串口助手。可以看到设计的串口工具可以完成串口收发数据,此外可以设置显示和发送的格式。

二、UI界面

波特率下拉栏添加了两个item:第一个115200,第二个9600。

数据位下拉栏添加了两个item:第一个8位,第二个6位。

校验位下拉栏添加了三个item:第一个无,第二个偶校验,第三个奇检验。

停止位下拉栏添加了三个item:第一个1位,第二个1.5位,第三个2位。

另外右下角红色指示灯实际上是一个Label,预设样式表代码为:

border-radius:5px;
background-color: rgb(255, 0, 0);

三、完整代码

(1).pro

        在 ".pro" 工程文件开头加入代码:引入Qt串口通信模块,用于实现串口数据的发送和接收。

QT       += serialport

(2)mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>//================================================添加头文件
#include <QSerialPort>      //串口
#include <QSerialPortInfo>  //串口
#include <QTimer>           //定时器
#include <QDateTime>        //获取当前时间
#include <QMessageBox>      //信息弹窗
#include <QDebug>           //用于调试
#include <QTextCodec>       //编码namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();//函数功能:将QString(16进制格式)转换为ByteArraystatic QByteArray hexStringToByteArray(const QString &hexString){QByteArray byteArray;QString sanitizedHex = hexString;//确保字符串长度是偶数if (sanitizedHex.length() % 2 != 0){sanitizedHex.prepend('0');//如果长度是奇数,前面补零}for (int i=0; i<sanitizedHex.length(); i+=2){QString byteString = sanitizedHex.mid(i,2);//取两位bool ok;byteArray.append(static_cast<char>(byteString.toInt(&ok,16)));//转为字节if (!ok){qDebug() << "Invalid hex byte:" << byteString;//字符串非16进制格式,转换报错}}return byteArray;//返回转换结果}private slots:void showTime();                        //获取时间void on_Button_check_clicked();         //点击检测串口按钮void on_Button_openserial_clicked();    //点击打开串口按钮void on_Button_clean_clicked();         //点击清空接收按钮void on_Button_send_clicked();          //点击发送按钮private:void initSerial();  //串口初始化void initTime();    //时间初始化void ReadData();    //串口读数据(接收数据)private:Ui::MainWindow  *ui;QSerialPort     *serial;    //串口对象QTimer          *timer;     //定时器QByteArray      buf;        //接收数据缓存
};#endif // MAINWINDOW_H

(3)mainwindow.cpp    

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);initTime();     // ============= 时间初始化initSerial();   // ============= 串口初始化
}MainWindow::~MainWindow()
{delete ui;
}//==========================================================//
//                      时间相关函数
//==========================================================//
void MainWindow::initTime() //时间初始化
{timer = new QTimer;// 信号连接、每一秒执行一次槽函数connect(timer,&QTimer::timeout,this,&MainWindow::showTime);timer->start(1000);
}
void MainWindow::showTime()//获取当前时间并显示
{//定义字符串currentTime = 获取当前时间并转换为字符串QString currentTime = QDateTime::currentDateTime().toString("时间: yyyy-MM-dd hh:mm:ss");ui->label_time->setText(currentTime);//设置标签内容
}//==========================================================//
//                      串口相关函数
//==========================================================//void MainWindow::initSerial() //串口初始化
{//获取可用串口名到下拉栏QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();for(int i=0; i<list.size(); i++){ ui->comboBox_port->addItem(list.at(i).portName()); }//创建串口对象serial = new QSerialPort;//连接信号与槽(接收数据)QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
}
void MainWindow::on_Button_openserial_clicked() //点击打开串口按钮
{if(ui->Button_openserial->text() == "打开串口") {//设置串口为下拉栏所选串口名serial->setPortName(ui->comboBox_port->currentText());//设置波特率switch (ui->comboBox_baud->currentIndex()) {case 0: serial->setBaudRate(QSerialPort::Baud115200); break;//115200case 1: serial->setBaudRate(QSerialPort::Baud9600);   break;default: break;}//设置数据位数switch (ui->comboBox_databit->currentIndex()) {case 0:serial->setDataBits(QSerialPort::Data8); break;//1位case 1:serial->setDataBits(QSerialPort::Data6); break;default: break;}//设置校验位switch (ui->comboBox_parity->currentIndex()) {case 0:serial->setParity(QSerialPort::NoParity);   break;//无校验位case 1:serial->setParity(QSerialPort::EvenParity); break;case 2:serial->setParity(QSerialPort::OddParity);  break;default: break;}//设置停止位switch (ui->comboBox_stopbit->currentIndex()) {case 0:serial->setStopBits(QSerialPort::OneStop); break;//1位case 1:serial->setStopBits(QSerialPort::OneAndHalfStop); break;case 2:serial->setStopBits(QSerialPort::TwoStop); break;default: break;}//设置流控制serial->setFlowControl(QSerialPort::NoFlowControl);//无流控制//打开串口 同时判断是否成功bool info = serial->open(QIODevice::ReadWrite);if(info == true) {qDebug()<<"success";//改变label颜色(指示灯)ui->label_light->setStyleSheet("background-color:rgb(0,255,0);border-radius:5px;");//关闭下拉栏设置使能ui->comboBox_port->setEnabled(false);ui->comboBox_baud->setEnabled(false);ui->comboBox_databit->setEnabled(false);ui->comboBox_parity->setEnabled(false);ui->comboBox_stopbit->setEnabled(false);//改变按钮文本为“关闭串口”ui->Button_openserial->setText(tr("关闭串口"));}else{ QMessageBox::critical(this, "Error", "串口打开失败:未检测到可用串口"); }}else {   //关闭串口serial->clear();serial->close();//改变label颜色(指示灯)ui->label_light->setStyleSheet("background-color:rgb(255,0,0);border-radius:5px;");//恢复下拉栏设置使能ui->comboBox_port->setEnabled(true);ui->comboBox_baud->setEnabled(true);ui->comboBox_databit->setEnabled(true);ui->comboBox_parity->setEnabled(true);ui->comboBox_stopbit->setEnabled(true);//改变按钮文本为“打开串口”ui->Button_openserial->setText(tr("打开串口"));}
}void MainWindow::on_Button_check_clicked() //点击检测串口按钮
{//获取可用串口名到下拉栏QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();ui->comboBox_port->clear(); // 清除之前检测到的串口for(int i=0; i<list.size(); i++){ ui->comboBox_port->addItem(list.at(i).portName()); }
}void MainWindow::on_Button_clean_clicked()  //点击清空接收按钮
{ui->textBrowser->clear();
}void MainWindow::on_Button_send_clicked()  //点击发送按钮
{//检查串口是否打开if (serial->isOpen()){if(ui->checkBox_16send->isChecked()==true) { //16进制发送被选中//获取要发送的数据:lineEdit_send内容QString sendData = ui->lineEdit_send->text();//将字符串转换为QByteArray形式(调用了hexStringToByteArray函数)QByteArray data  = hexStringToByteArray(sendData);//发送数据serial->write(data);}else {//获取要发送的数据:lineEdit_send内容QString sendData = ui->lineEdit_send->text();//将字符串转为QByteArrayQByteArray data  = sendData.toUtf8();//发送数据serial->write(data);}}else {qDebug()<<"serial is not open";QMessageBox::critical(this, "Error", "发送失败:请打开串口");}
}void MainWindow::ReadData()//==================================== 读取接收到的信息
{// 1. 读取数据并追加到缓存 (.h头文件已声明 QByteArray buf)buf.append(serial->readAll()); //或QByteArray buf = serial->readAll();// 2. 判断数据显示格式QString displayData; //定义最后显示出来的字符串if (ui->checkBox_16rec->isChecked()==true) { //16进制显示被选中QString hexData= buf.toHex().toUpper(); //将数据转换为16进制字符串并大写QString spacedData;                     //用于存储每个字节隔开一个空格的字符串for(int i=0;i<hexData.length();i+=2) {  //在每个字节后添加一个空格spacedData += hexData.mid(i,2);spacedData += " ";}displayData = spacedData; //显示转换后的数据}else { //非十六进制显示QTextCodec *gbkCodec = QTextCodec::codecForName("GBK");//使用GBK编码解析(解决中文乱码)displayData = gbkCodec->toUnicode(buf);}// 3. 添加时间戳,显示接收数据QString currentTime = QDateTime::currentDateTime().toString("Rx: [hh:mm:ss]");//获取当前时间currentTime = QString("<span style='color: red;'>%1</span>").arg(currentTime);//设置时间戳为红色ui->textBrowser->append(currentTime);   //显示时间戳ui->textBrowser->append(displayData);   //显示接收数据buf.clear(); //清空接收缓存
}

(4)main.cpp    

        mian.cpp里面有两行被注释掉的的代码,主要是用于适应屏幕放缩用的,如果ui运行出来布局和设计的摆放布局不一致或者是错位了,可以尝试通过这两行代码解决。

#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{//自适应放缩(用于屏幕分辨率改变会使窗口布局大小变化)//if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))//  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling,true);QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
http://www.dtcms.com/a/399383.html

相关文章:

  • 【Unity 入门教程】一、前置工作
  • 北京网站建设公司空间续费北京建设工程施工司法解释
  • 需求收集不完整的常见原因有哪些
  • 论坛网站备案开发者选项在哪里打开vivo
  • 谈谈数组和链表的时间复杂度
  • ServletContex读取properties文件,中文乱码
  • todesk取消客户端开机自动启动后,开机仍然会启动客户端,怎么设置?
  • C++编程学习(第36天)
  • 如何快速处理电脑上常常遇到的各种小问题?
  • 卷积神经网络(CNN)的LeNet模型
  • 佛山网站外包什么是网站推广方案
  • 合肥门户网站制作建设佛山cms建站
  • Linux命令大全-usermod命令
  • Linux网络HTTP协议(上)
  • 开源 java android app 开发(十四)自定义绘图控件--波形图
  • umijs 4.0学习 - umijs 的项目搭建+自动化eslint保存+项目结构
  • 汇天网络科技有限公司苏州关键词优化软件
  • 制冷剂中表压对应温度值的获取(Selenium)
  • 建什么网站访问量高seo优化
  • 小型网站建设参考文献word超链接网站怎样做
  • 可视化 GraphRAG 构建的知识图谱 空谈版
  • 安装gitlab并上传本地项目
  • 黄页88网站免费推广网站大全网
  • 深圳附近建站公司做企业网站有什么工作内容
  • 新能源知识库(104)什么是FAT和SAT?
  • 多元函数可微性的完整证明方法与理解
  • 长春建站培训wordpress广告先显示
  • 怎么做网页版手机版网站百度竞价托管公司
  • 【寰宇光锥舟】Bash 脚本详细解释
  • 如何高效解析复杂表格