手把手教你用Qt写个串口上位机

原创 电子电路开发学习 2024-03-13 19:30


前言

最近刚学了一点Qt开发上位机,尝试着做个小软件练练手。查找了很多资料,做了一个简单的串口助手,可以实现串口基本发送和接收功能,支持中文显示,还可以控制STM32开发板上的两个LED。

1.软件界面

2.主要功能:

  • 启动自动搜索本机串口,或者手动点击搜索键扫描串口

  • 自定义波特率

  • 支持中文显示

  • 支持发送新行

3.实际效果:

(GIF压缩后根本没法看。。。。)

花了大概3天时间吧,找了很多资料,功能很简单, 但想着是自己一点一点开发的,还是挺有成就感的哈!

写这篇文章是为了总结一下开发的过程和一些知识点,主要包括两部分,上位机的实现和STM32端程序的实现。

Qt上位机的实现

0.新建一个Dialog项目

新建一个Dialog项目,这3种基类的区别可以根据你的程序来确定。

  • 如果需要嵌入到其他窗体中,则基于QWidget创建。

  • 如果是主窗体,则基于QMainWindow创建,有菜单栏,状态栏,工具栏等。

  • 如果是顶级对话框,则基于QDialog创建。


1.软件UI界面的设计

使用Qt Designer添加所需要的控件,并进行合理布局,尽量每一个控件,起一个合理易懂的名字。

2.串口库的添加

pro文件添加一行:

  1. QT += serialport

对应的头文件包含:

  1. #include <QSerialPort>

  2. #include <QSerialPortInfo>

3.串口自动搜索功能的实现

自动搜索本机串口,并在ComboBox中添加串口号

  1. ui->cbb_com->clear();

  2. //运行开始查找可用串口

  3. foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())

  4. {

  5. ui->cbb_com->addItem(info.portName()); //串口号下拉菜单,增加一个条目,为串口号COM4

  6. qDebug() << "串口搜索完成";

  7. }

4.串口的配置和打开关闭

  1. //打开串口按钮

  2. void Dialog::on_btn_uart_Ctrl_clicked()

  3. {

  4. // static bool flag; //也可以用标志位实现

  5. if(this->ui->btn_uart_Ctrl->text() == "打开串口") //初始状态,配置串口参数

  6. {

  7. serial.setPortName(ui->cbb_com->currentText()); //设置串口号、

  8. serial.setBaudRate(ui->cbb_baud->currentText().toInt()); //设置波特率

  9. serial.setDataBits(QSerialPort::Data8); //设置串口数据位8

  10. serial.setParity(QSerialPort::NoParity); //无校验位

  11. serial.setStopBits(QSerialPort::OneStop); //1位停止位

  12. serial.setFlowControl(QSerialPort::NoFlowControl);

  13. //打开串口

  14. if(!serial.open(QIODevice::ReadWrite))

  15. {

  16. QMessageBox::critical(NULL, "提示", "串口打开失败");

  17. return;

  18. }

  19. qDebug() << "串口打开成功";

  20. this->ui->btn_uart_Ctrl->setText("关闭串口");

  21. }

  22. else

  23. {

  24. //关闭串口

  25. serial.close();

  26. this->ui->btn_uart_Ctrl->setText("打开串口");

  27. }

  28. }

5.串口发送数据

  1. serial.write("A1\n"); //串口发送A1

6.串口数据的接收和显示,支持中文

QT默认的编码是unicode,不能显示中文的,windows默认使用(GBK/GB2312/GB18030),使用了fromLocal8Bit()函数,实现了从Unicode到本地字符集GBK的转换,用于处理汉语显示乱码等问题

槽函数的实现:

  1. //串口数据接收并显示

  2. void Dialog::serialPort_readyRead()

  3. {

  4. QByteArray rx_buf = serial.readAll(); //读取串口接收的数据

  5. if(rx_buf.endsWith("\r\n")) //判断接收最后是否是回车换行,即接收完成标志

  6. {


  7. }

  8. QString rx_buf_tmp = QString::fromLocal8Bit(rx_buf); //转换为中文格式

  9. qDebug() << rx_buf_tmp; //控制台输出


  10. ui->tb_rx_buf->append(rx_buf_tmp);


  11. rx_buf_tmp.clear();

  12. rx_buf.clear();

  13. }

connect语句:

  1. connect(&serial, & QSerialPort::readyRead, this, &Dialog::serialPort_readyRead);

7.下拉框自定义波特率的实现

  1. //自定义波特率

  2. void Dialog::on_cbb_baud_currentIndexChanged(const QString &arg1)

  3. {

  4. if(this->ui->cbb_baud->currentIndex() == 3)

  5. {

  6. this->ui->cbb_baud->setItemText(3, ""); //调成自定义波特率时,内容设置为空,准备接收输入

  7. this->ui->cbb_baud->setEditable(true);

  8. }

  9. else

  10. {

  11. this->ui->cbb_baud->setItemText(3, "自定义"); //调成自定义波特率时,内容设置为空,准备接收输入

  12. this->ui->cbb_baud->setEditable(false);

  13. }

  14. serial.setBaudRate(ui->cbb_baud->currentText().toInt()); //即使打开串口后,仍然可以设置波特率

  15. }

8.发送新行功能的实现

通过一个全局变量实现,发送新行按钮勾选时,标志位置1,然后发送按钮功能里,根据标志位决定是否在末尾添加换行符。

对应的槽函数实现:

  1. //是否发送新行

  2. void Dialog::on_cb_send_enter_clicked()

  3. {

  4. if(ui->cb_send_enter->isChecked())

  5. {

  6. send_enter_flag = true;

  7. qDebug() << "发送新行";

  8. }

  9. else

  10. {

  11. send_enter_flag = false;

  12. qDebug() << "不发送新行";

  13. }

  14. }

  15. //发送按钮被按下

  16. void Dialog::on_btn_send_clicked()

  17. {

  18. //获取多行输入框的数据并转换为UTF8格式

  19. QByteArray tx_buf = ui->te_tx_buf->toPlainText().toUtf8();


  20. if(send_enter_flag == true)

  21. tx_buf += "\n";


  22. serial.write(tx_buf); //把数据通过串口发送出去

  23. tx_buf.clear();

  24. }

9.只改变标签颜色

本来想着通过改变样式表的方式改变颜色

  1. this->ui->lbe_blue->setStyleSheet("color: rgb(255, 0, 0);");

但是,实际运行时,连字体和大小都改成了默认的,有没有一种只改变颜色其他的格式不变的方法呢?还真有,如下,不过好像只支持标准颜色?

  1. QPalette colr;

  2. colr.setColor(QPalette::WindowText,Qt::red); //设置标签颜色红色

  3. this->ui->lbe_red->setPalette(colr);

10.按钮的使能失能控制

以下两行语句效果相同,都是失能按钮功能:

  1. this->ui->btn_led1_Ctrl->setDisabled(true); //LED控制按钮不可用

  2. this->ui->btn_led1_Ctrl->setEnabled(false); //LED控制按钮不可用

11.文本显示框设置最大显示行数

  1. this->ui->tb_rx_buf->document()->setMaximumBlockCount(10);

程序的图标、标题设置和打包发布

你不希望窗口的标题是“Dialog”吧,所以添加一个标题和一个好看的图标还是很有必要的。

1.添加标题

添加窗口标题还是很简单的,一行代码:

  1. this->setWindowTitle("串口控制LED - By wcc ");

2.添加icon图标

  • 找一个好看的图标,格式一定要是.ico,像素大小推荐128*128

  • 命名为my_app.ico,名字无所谓,不要有中文就好了,放在工程目录下,即和.pro文件和.cpp文件同一个目录。

  • 打开.pro文件,最底下添加一行:RCICONS = myapp.ico

重新编译就可以看到这种效果了。

3.程序文件的生成

构建选项改成Release版本,编译完成后,会在Release目录下生成一个.exe文件,把这个文件单独拷出来放在一个空白的文件夹里,如 D:\QT_Prj\Export\UART_Demo.exe,可以运行试一下,会提示缺少运行所需要的dll组件

而且,这个文件如果单独拷贝到其他没有安装Qt环境的电脑上,也是不能运行的。

所以我们需要添加一些当前程序运行所需要的组件才能正常运行,但是需要添加哪些文件呢?不用担心,Qt早已经想好了,运行MinGW工具:

先进入到exe文件所在的文件夹中: cd/d D:\QT_Prj\Export

然后输入命令: windeployqt UART_Demo.exe

此时,打开exe文件所在的文件夹,可以看到Qt已经为我们添加好了,当前程序运行所需要的组件了。

这个时候,如果想给别人分享你开发好的上位机软件,就可以直接把这个文件夹拷贝给他。当然也可以安装一个 EnigmaVirtualBox软件,把当前目录下的所有文件打包成一个exe文件。

STM32端程序的实现

连接串口模块,发送接收短接,可以看出Qt上位机的的收发都是正常的。下一步就是编写STM32端的程序了,很简单,当接收到字符串"A1"时,点亮红灯;当接收到字符串“A2”时,熄灭红灯;当接收到字符串“B1”时,点亮蓝灯;当接收到字符串“B2”时,熄灭蓝灯,每个字符串结尾都有换行符“\n”。

实现思路也很简单,即把接收到的字符存入一个字符数组,当接收到“\n”换行标志时,意味着接收完成,判断此时数组的内容,分别和命令比较,如果一致,执行相应的操作,串口1中断服务函数:

  1. void USART1_IRQHandler(void)

  2. {

  3. char dat;

  4. char flag = 0;

  5. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断

  6. {

  7. dat = USART1->DR;

  8. if(usart1Len >= 64) //防止数据过多,导致内存溢出

  9. usart1Len = 0;

  10. if(dat == 0x0D || dat == 0x0A) //回车换行,接收完成,此时的buf不含回车换行

  11. {

  12. if(strcmp(usart1Buf, "A2") == 0) //字符串比较

  13. {

  14. UsartPrintf(USART1, "红灯熄灭\r\n");

  15. GPIO_SetBits(GPIOB, GPIO_Pin_9);

  16. }

  17. else if(strcmp(usart1Buf, "A1") == 0)

  18. {

  19. UsartPrintf(USART1, "红灯点亮\r\n");

  20. GPIO_ResetBits(GPIOB, GPIO_Pin_9);

  21. }

  22. else if(strcmp(usart1Buf, "B2") == 0)

  23. {

  24. UsartPrintf(USART1, "蓝灯熄灭\r\n");

  25. GPIO_SetBits(GPIOB, GPIO_Pin_6);

  26. }

  27. else if(strcmp(usart1Buf, "B1") == 0)

  28. {

  29. UsartPrintf(USART1, "蓝灯点亮\r\n");

  30. GPIO_ResetBits(GPIOB, GPIO_Pin_6);

  31. }

  32. usart1Len = 0;

  33. memset(usart1Buf,0,64);

  34. }

  35. else

  36. {

  37. usart1Buf[usart1Len++] = dat;

  38. }

  39. USART_ClearFlag(USART1, USART_FLAG_RXNE);

  40. }

  41. }

程序还是很简单。板子是用的中移的麒麟座Mini板,基于F103C8T6的,串口1连接上位机,波特率115200,PB9-红灯,PB6-绿灯,都是低电平点亮。

改进和优化的地方

  • 按钮发送字符可自定义

  • 界面UI的设计优化

  • 数据波形的显示

  • 发送和接收,16进制和字符模式的切换

  • 定时发送功能

  • 接收内容保存成文件

  • 一个小Bug,不支持多个串口的自动搜索。

Qt工程和STM32工程下载

由于国内Github下载速度实在令人着急,Qt工程文件和STM32工程文件,还包括EnigmaVirtualBox的安装包,我都已经上传到国内的码云Gitee上了,有需要的朋友可以在Git中使用以下命令下载:

  1. git clone https://gitee.com/whik/qt_uart_demo.git

或者是在公众号后台回复【串口助手】,我会把下载链接发送给你。

当然,如果有朋友也在学习Qt开发上位机,欢迎互相交流学习。

​​

更多

  • 使用STM32获取东京奥运奖牌榜

  • 使用STM32获取疫苗接种数据

  • 使用STM32获取新冠肺炎疫情数据

  • 如何写出易于维护的Verilog代码?

  • FPGA如何进行片上调试

  • 一文看懂Modbus协议

  • 一文看懂I2C协议

  • 一文看懂SPI协议

电子电路开发学习 单片机点灯小能手,电子行业从业者。开发板评测、嵌入式开源项目分享、学习笔记记录。可能不会经常更新,但每一篇都是精心编写。
评论 (0)
  • ## DL/T645-2007* 帧格式:* 帧起始字符:68H* 地址域:A0 A1 A2 A3 A4 A5* 帧起始字符:68H* 控制码:1字节* 主站:* 13H:请求读电能表通信地址* 11H:请求读电能表数据* 1CH:请求跳闸、合闸* 从站:* 91H:正常应答读电能表* 9CH:正常应答跳闸、合闸* 数据域长度:1字节* 数据域:DI0 DI1 DI2 DI3* 发送方:每字节+33H* 接收方:每字节-33H* 数据标识:* 电能量* 最大需量及发生时间* 变量* 事件记录*
    四毛打印店 2025-04-09 10:53 59浏览
  • 在万物互联时代,智能化安防需求持续升级,传统报警系统已难以满足实时性、可靠性与安全性并重的要求。WT2003H-16S低功耗语音芯片方案,以4G实时音频传输、超低功耗设计、端云加密交互为核心,重新定义智能报警设备的性能边界,为家庭、工业、公共安防等领域提供高效、稳定的安全守护。一、技术内核:五大核心突破,构建全场景安防基座1. 双模音频传输,灵活应对复杂场景实时音频流传输:内置高灵敏度MIC,支持环境音实时采集,通过4G模块直接上传至云端服务器,响应速度低至毫秒级,适用于火灾警报、紧急呼救等需即
    广州唯创电子 2025-04-08 08:59 156浏览
  •   物质扩散与污染物监测系统软件:多领域环境守护的智能中枢   北京华盛恒辉物质扩散与污染物监测系统软件,作为一款融合了物质扩散模拟、污染物监测、数据分析以及可视化等多元功能的综合性工具,致力于为环境科学、公共安全、工业生产等诸多领域给予强有力的技术支撑。接下来,将从功能特性、应用场景、技术实现途径、未来发展趋势等多个维度对这类软件展开详尽介绍。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这
    华盛恒辉l58ll334744 2025-04-09 14:54 114浏览
  • 文/郭楚妤编辑/cc孙聪颖‍伴随贸易全球化的持续深入,跨境电商迎来蓬勃发展期,物流行业 “出海” 成为不可阻挡的必然趋势。加之国内快递市场渐趋饱和,存量竞争愈发激烈。在此背景下,国内头部快递企业为突破发展瓶颈,寻求新的增长曲线,纷纷将战略目光投向海外市场。2024 年,堪称中国物流企业出海进程中的关键节点,众多企业纷纷扬帆起航,开启海外拓展之旅。然而,在一片向好的行业发展表象下,部分跨境物流企业的经营状况却不容乐观。它们受困于激烈的市场竞争、不断攀升的运营成本,以及复杂的国际物流环境,陷入了微利
    华尔街科技眼 2025-04-09 15:15 93浏览
  • 文/Leon编辑/侯煜‍就在小米SU7因高速交通事故、智驾性能受到质疑的时候,另一家中国领先的智驾解决方案供应商华为,低调地进行了一场重大人事变动。(详情见:雷军熬过黑夜,寄望小米SU7成为及时雨)4月4日上午,有网友发现余承东的职务发生了变化,华为官网、其个人微博认证信息为“常务董事,终端BG董事长”,不再包括“智能汽车解决方案BU董事长”。余承东的确不再兼任华为车BU董事长,但并非完全脱离华为的汽车业务,而是聚焦鸿蒙智行。据悉,华为方面寻求将车BU独立出去,但鸿蒙智行仍留在华为终端BG部门。
    华尔街科技眼 2025-04-09 15:28 93浏览
  • 在人工智能技术飞速发展的今天,语音交互正以颠覆性的方式重塑我们的生活体验。WTK6900系列语音识别芯片凭借其离线高性能、抗噪远场识别、毫秒级响应的核心优势,为智能家居领域注入全新活力。以智能风扇为起点,我们开启一场“解放双手”的科技革命,让每一缕凉风都随“声”而至。一、核心技术:精准识别,无惧环境挑战自适应降噪,听懂你的每一句话WTK6900系列芯片搭载前沿信号处理技术,通过自适应降噪算法,可智能过滤环境噪声干扰。无论是家中电视声、户外虫鸣声,还是厨房烹饪的嘈杂声,芯片均能精准提取有效指令,识
    广州唯创电子 2025-04-08 08:40 192浏览
  •   物质扩散与污染物监测系统:环境守护的关键拼图   一、物质扩散原理剖析   物质扩散,本质上是物质在浓度梯度、温度梯度或者压力梯度等驱动力的作用下,从高浓度区域向低浓度区域迁移的过程。在环境科学范畴,物质扩散作为污染物在大气、水体以及土壤中迁移的关键机制,对污染物的分布态势、浓度动态变化以及环境风险程度有着直接且重大的影响。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这些成功案例为物质
    华盛恒辉l58ll334744 2025-04-09 11:24 57浏览
  • HDMI从2.1版本开始采用FRL传输模式,和2.0及之前的版本不同。两者在物理层信号上有所区别,这就需要在一些2.1版本的电路设计上增加匹配电路,使得2.1版本的电路能够向下兼容2.0及之前版本。2.1版本的信号特性下面截取自2.1版本规范定义,可以看到2.1版本支持直流耦合和交流耦合,其共模电压和AVCC相关,信号摆幅在400mV-1200mV2.0及之前版本的信号特性HDMI2.0及之前版本采用TMDS信号物理层,其结构和参数如下:兼容设计根据以上规范定义,可以看出TMDS信号的共模电压范
    durid 2025-04-08 19:01 172浏览
  •   卫星图像智能测绘系统:地理空间数据处理的创新引擎   卫星图像智能测绘系统作为融合卫星遥感、地理信息系统(GIS)、人工智能(AI)以及大数据分析等前沿技术的综合性平台,致力于达成高精度、高效率的地理空间数据采集、处理与应用目标。借助自动化、智能化的技术路径,该系统为国土资源管理、城市规划、灾害监测、环境保护等诸多领域输送关键数据支撑。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉北京五木恒润卫星图像智能测绘系统。这些成功案例为卫星
    华盛恒辉l58ll334744 2025-04-08 16:19 86浏览
  •   卫星图像智能测绘系统全面解析   一、系统概述   卫星图像智能测绘系统是基于卫星遥感技术、图像处理算法与人工智能(AI)技术的综合应用平台,旨在实现高精度、高效率的地理空间数据获取、处理与分析。该系统通过融合多源卫星数据(如光学、雷达、高光谱等),结合AI驱动的智能算法,实现自动化、智能化的测绘流程,广泛应用于城市规划、自然资源调查、灾害监测等领域。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润卫星图像智能测绘系统
    华盛恒辉l58ll334744 2025-04-08 15:04 99浏览
我要评论
0
4
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦