电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
使用Qt打造属于自己的串口调试助手
分 享
扫描二维码分享
使用Qt打造属于自己的串口调试助手
Qt
串口助手
串口通信
嵌入式从0到1
关注
发布时间: 2021-01-20
丨
阅读: 1271
在我的工作中,可能打交道最多的就是串口通信了,与单片机进行数据通信,串口无疑是最简单的方式,今天我们使用Qt实现一个自己的串口调试助手。 ### 实现目标 自己编写一个基于Qt的串口调试软件,可以实现本软件与串口助手之间的通讯。 软件发送的数据,经虚拟串口转发,能够在串口助手中正确接收; 串口助手发送的数据可以在本软件的接收文本框中显示,进而实现串口数据双向通信。 ### 所需工具及环境 * 虚拟串口软件(用于创建一对虚拟串口) * Qt Creator 4.10.1 * Qt 5.13.1 * XCOM V2.0 串口助手 * 本人电脑 Windows 10 64bit [版本 10.0.19041.329] ### 本文源码 ![工程所在文件夹](https://img-blog.csdnimg.cn/20210117233930326.png) ![Qt Creator中工程目录](https://img-blog.csdnimg.cn/2021011723395765.png) 后台回复关键字“**Qt-COM**”,获取本文涉及到的虚拟串口软件及Qt工程源码。 ### 界面设计 利用Qt Creator新建一个Project,模板选择 **Application--> Qt Widgets Application** , 向导中 **Class Information** 页面中,**Base class** 选择 **QMainWindow** 、 **QWidget** 、**QDialog** 都可以。 工程创建完毕,**.ui** 文件具体设计如下: ![](https://img-blog.csdnimg.cn/20210117234027511.png) ### 具体实现 #### 导入串口通信模块 从Qt 5.1版本开始,Qt就有了自己的串口通讯类,之前版本需要使用第三方的串口通信类才行。 要想使用串口通信类,需要在 **.pro** 文件中添加 **QT += serialport** ![](https://img-blog.csdnimg.cn/20210117234042398.png) #### 显示系统中所有串口号 显示串口号列表的是一个**QComboBox**控件。 ![](https://img-blog.csdnimg.cn/20210117234056675.png) 我们调用 **QSerialPortInfo::availablePorts()** 可以获得一个 **QList
** ,List中的每一项 **QSerialPortInfo** 代表一个串口实例,该类中保存了系统中已有串口的端口名称、系统位置、描述和供应商等信息。 ![](https://img-blog.csdnimg.cn/2021011723410626.png) 遍历系统中所有串口名的实现代码如下: ```C QStringList MainWindow::getPortNameList() { QStringList m_serialPortName; foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { m_serialPortName << info.portName(); qDebug()<<"serialPortName:"<
**,将串口名称保存至 **m_serialPortName** 变量中,这个变量的类型是 **QStringList** , 将最终结果显示在 QComboBox中: ```C m_portNameList = getPortNameList(); ui->comboBoxPortName->addItems(m_portNameList); ``` #### 打开串口 串口的打开涉及到如下函数: ```C //判断串口是否已打开 bool QIODevice::isOpen() const //清空缓冲区 bool QSerialPort::clear(QSerialPort::Directions directions = AllDirections) //串口关闭 [override virtual] void QSerialPort::close() //设置要打开的串口名 void QSerialPort::setPortName(const QString &name) //设置串口通信的波特率 bool QSerialPort::setBaudRate(qint32 baudRate, QSerialPort::Directions directions = AllDirections) //设置串口通信的数据位,数据位一般为8位 bool QSerialPort::setDataBits(QSerialPort::DataBits dataBits) //设置串口通信的流控制,一般无需流控制 bool QSerialPort::setFlowControl(QSerialPort::FlowControl flowControl) //设置串口通信的奇偶校验,一般选择“无” bool QSerialPort::setParity(QSerialPort::Parity parity) //设置串口通信的停止位,停止位一般为1 bool QSerialPort::setStopBits(QSerialPort::StopBits stopBits) ``` 在“**打开串口**”按钮上右键弹出菜单中,选择 **转到槽...** ,在按键的 **clicked()** 事件中,添加串口打开的对应代码。 ![](https://img-blog.csdnimg.cn/20210117234119366.png) 串口通信类库通信过程基本是一下步骤,即:打开串口 --> 配置串口参数(波特率、数据位、停止位、奇偶校验、流控等) --> 收发数据。 串口打开的具体实现如下: ```C void MainWindow::on_btnOpenCOM_clicked() { if (ui->btnOpenCOM->text()=="打开串口") { if(m_serialPort->isOpen()) { m_serialPort->clear(); m_serialPort->close(); } m_serialPort->setPortName(m_portNameList[ui->comboBoxPortName->currentIndex()]); if(!m_serialPort->open(QIODevice::ReadWrite)) { qDebug()<
comboBoxPortName->currentIndex()]<<"打开失败!"; return; } //打开成功 m_serialPort->setBaudRate(ui->comboBoxBaudRate->currentText().toInt(),QSerialPort::AllDirections);//设置波特率和读写方向 m_serialPort->setDataBits(QSerialPort::Data8); //数据位为8位 m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //无流控制 m_serialPort->setParity(QSerialPort::NoParity); //无校验位 m_serialPort->setStopBits(QSerialPort::OneStop); //一位停止位 connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); ui->btnOpenCOM->setText("关闭串口"); } else { m_serialPort->close(); ui->btnOpenCOM->setText("打开串口"); } } ``` #### 串口发送数据 串口发送数据的函数为: ```C qint64 QIODevice::write(const char *data) ``` 这个函数是将以‘/0’结尾的字符串中的数据写入设备(‘\0’以后的数据都丢掉了)。返回实际写入的字节数,如果发生错误则返回-1。 我们根据界面中,**Hex发送**复选框是否勾选,判断发送的字符串是否将其转为十六进制,然后调用 **qint64 QIODevice::write(const char \*data)** 函数,将QByteArray数组发送至设备端。 **发送**按钮点击后的事件具体实现如下: ```C void MainWindow::on_btnSendData_clicked() { QString m_strSendData = ui->txtSend->text(); if(ui->checkBoxHexSend->isChecked()) { if (m_strSendData.contains(" ")) { m_strSendData.replace(QString(" "),QString("")); //把空格去掉 } QByteArray sendBuf; convertStringToHex(m_strSendData, sendBuf); //把QString 转换 为 hex m_serialPort->write(sendBuf); } else { m_serialPort->write(m_strSendData.toLocal8Bit()); } } ``` #### 串口接收数据 当缓冲区中收到串口数据的时候,**readyRead()** 信号将被发射,我们定义个槽 **void receiveInfo()** 来解析收到的数据。 ```C connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); ``` 下面就是接收函数的完整实现,如果想要解析下位机发送来的数据,就在此函数中实现数据包的解析。 ```C void MainWindow::receiveInfo() { qDebug()<<"receiveInfo()"; QByteArray info = m_serialPort->readAll(); QString strReceiveData = ""; if(ui->checkBoxHexReceive->isChecked()) { QByteArray hexData = info.toHex(); strReceiveData = hexData.toUpper(); qDebug()<<"接收到串口数据: "<
txtReceiveData->append(strReceiveData); } else { strReceiveData = info; //避免中文乱码 QTextCodec *tc = QTextCodec::codecForName("GBK"); QString tmpQStr = tc->toUnicode(info); ui->txtReceiveData->append(tmpQStr); } //ui->txtReceiveData->append("\r\n"); } ``` 详细源码请参考Qt工程文件。 ### 创建虚拟串口 要想测试咱们的串口助手是否正确,可以使用一个USB转TTL模块,然后短接其发送和接收引脚,自发自收,看看发送的内容是否能够正确接收。 或者使用 **VSPD.exe** 软件创建几对虚拟串口,成对的虚拟串口从一个串口发出的数据另外一个串口能够收到,反之一样。 ![](https://img-blog.csdnimg.cn/20210117234150478.png) ### 结果展示 ![](https://img-blog.csdnimg.cn/20210117234202235.gif) ### Qt小知识 #### 查看在线帮助文档 右键某一个Qt自带类,然后右键菜单中选择:**上下文相关帮助 F1**,Qt Creator右侧即会弹出此类的帮助文档。 ![](https://img-blog.csdnimg.cn/20210117234210662.png) ### 欢迎关注 公众号【嵌入式从0到1】专注于嵌入式知识分享,学习路上不迷路。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
嵌入式从0到1
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交