0 引言
上一篇博文中简要介绍了king3399板子串口的硬件电路、设备树以及驱动等部分,但大多数情况下我们更多的是通过串口来与外部设备进行通信,因此本篇博文将使用Qt(C++)来开发一个简单的串口工具
1 硬件环境快速验证
在编写串口工具时,需要准备如下器材/软件:两个USB转串口模块,三根母头杜邦线,串口调试助手(这里使用“串口猎人 ( Serial Hunter ) V31.exe”,该工具功能强大,使用简单、稳定且免费,可自行在网上下载),需要注意的是两个USB转串口模块的RX与TX需要交叉连接
,设备连接如下图所示:
在电脑上打开两个串口调试助手(串口猎人),将两者的波特率、校验位、数据位与停止位设置为一致,然后点击打开串口,并在发送栏相互发送数据,此时两个串口助手的接收栏都会显示发送的数据,说明串口通信成功,这一步个人认为是比较重要的,因为USB转串口模块是易耗品,经常会出现烧坏无法使用的情况,因此在使用之前最好先进行测试,确保串口通信成功
2 Qt官方SerialPort参考源码下载
Qt官方对于SerialPort提供了详细的说明文档与参考源码,建议先花点时间将大概内容与例子看看,这样在开发时能有权威参考,并在遇到问题时可以快速定位问题,这里给出官方参考源码下载地址(步骤):在ubuntu中打开Qt并按照如下步骤(1-7)找到参考源码链接(下图标示7处),将该链接复制,打开Git码云,按照步骤(8-13)下载
在帮助手册中可以看到串口通信可以分为同步/异步(阻塞/非阻塞),在Help - Qt Serial Port - Examples - Blocking Slave Example
有明确提到The purpose of this example is to demonstrate a pattern that you can use to simplify your serial programming code, without losing responsiveness in your user interface. Use of Qt's blocking serial programming API often leads to simpler code, but because of its blocking behavior, it should only be used in non-GUI threads to prevent the user interface from freezing. But contrary to what many think, using threads with QThread does not necessarily add unmanageable complexity to your application.
,我们的工具需要使用到界面,为降低开发难度,突出本文重点,因此这里选择异步通信(非阻塞)作为主要参考
3 ubuntu下相关配置
在编写上位机软件时遇到以下四个问题:
(1) Input/Output error
,这主要是由于未添加有关串口相应设备,解决方案参考脚注【a】
(2) Could not load the Qt platform plugin "xcb"
,这主要是由于未添加相关依赖库,解决方案参考脚注【b】,本人在使用该方案时未能完美解决我所遇到的问题,综合了几篇博文进行了如下总结:
在虚拟机上调试时,点击run
后可能出现如下错误:qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
,这是一个比较笼统的错误,无法定位到具体的错误原因,此时可以通过以下步骤进行定位:
- 在虚拟机中关闭Qt Creator软件
- 找到Qt Creator安装目录,一般为
~/Qt5.12.2/Tools/QtCreator/bin
- 在上述目录下执行
./qtcreator
(执行前可先查看该目录下有无该文件) - 打开软件后再次点击
run
,此时会在Application Output
显示具体的信息 - 以本人电脑为例,出现如下错误:
- 信息显示
libxcb-xinerama.so.0: cannot open shared object file: No such file or directory
- 在虚拟机中安装
libxcb-xinerama0
:sudo apt-get install libxcb-xinerama0
- 此时再点击
run
,界面正常显示 - 为了从命令行启动Qt Creator,可将
qtcreator
文件路径添加到``~/.bashrc`文件中: - 在.bashrc文末添加:export PATH=“~/xxx/Tools/QtCreator/bin:$PATH”(根据自己路径添加)
- 保存后执行
source ~/.bashrc
,重启终端,此时可在命令行通过qtcreator
打开软件
// ------------------错误信息--------------------
Got keys from plugin meta data ("xcb")e
QFactoryLoader::QFactoryLoader() checking directory path "/home/xxx.../Desktop_Qt_5_15_2_GCC_64bit-Debug/platforms" ...
Cannot load library /home/xxx.../platforms/libqxcb.so: (libxcb-xinerama.so.0: cannot open shared object file: No such file or directory)
QLibraryPrivate::loadPlugin failed on "/home/xxx.../platforms/libqxcb.so" : "Cannot load library /home/xxx.../platforms/libqxcb.so: (libxcb-xinerama.so.0: cannot open shared object file: No such file or directory)"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, xcb.
(3) Permission denied
,这主要是由于未添加相应权限,因为串口设备是在目录 /dev/tty下的,当我们以普通用户去读写这个文件时,会出现权限不够的情况,解决方案参考脚注【c】,本人使用的是该脚注中提到的“解决方法(一)”
(4) 在虚拟机中开发、调试并运行软件,相对于以上三点,第(4)点并不是一个错误,而是为了方便开发,该串口工具为交叉编译生成,运行平台的框架为arm,如果每次编译完都传到板子上打开查看效果,开发过程会比较繁琐,为便于软件调试,可先在虚拟机中调试,然后再移植到开发板上,因此在创建qt工程选择kits时需要同时选择armqt
与Desktop Qt 5.12.2.GCC 64bit
,(注意:这两个kit名不尽相同,根据自己的情况选择)前者用于板子,后者用于虚拟机,在虚拟机上调试时,按照下图步骤(1~4)操作
4 串口工具开发
虽然本文的题目是说串口工具开发,但并不会去讲详细的过程,因为在读这篇博文的时候就应该知道/使用过一种或多种串口工具,那么在使用这些工具的时候,哪些功能是必须的,哪些是常用的心里应该有数,这里将最近做的串口工具与大家分享一下,工程源码在文末仓库中,由于这个工具并未实际运用于某个项目中,仅仅只是练手,因此写的比较潦草,也存在一些小bug,仅供参考,下图为该工具的主界面
界面主要分为(a~g)七个部分,下表是各部分的介绍
模块 | 功能描述 |
---|---|
a 串口配置 | Search : 搜索串口,在虚拟机上时这里会比较卡,点击一次可能会卡个3~5秒,而且还可能无法搜索到有用的串口,多数情况需要点击个3~4次才能搜索到串口,而交叉编译后生成的文件在板子上执行搜索时很流畅,原因未知,最终搜索到的串口会被添加到下方的下拉框中(图中“tportName”处) |
Close : 打开或者关闭串口 | |
Parity : 选择校验位,默认无校验 DataBits : 选择数据位,默认8位 StopBits : 选择停止位,默认1位 BaudRate : 选择波特率,默认9600 |
|
b 接收配置 | Hex / String : 以十六进行或是字符格式显示 |
StopShow : 停止显示,这个功能主要用于有时会接收大量数据,而我们需要暂停数据在 e 中的刷新去分析某一段数据 | |
Debug : 预留,没有实现任何功能,以前在windows下使用Qt写的串口工具在接收大量数据时(大量的数据在接收框中刷新时)会出现运行一段时间卡死的现象,当勾选这个功能时,可以短时间进入调试模式(大量数据在接收框中刷新)进而分析数据 | |
Clear : 清空接收框 e | |
Save : 将接收框中数据保存到.txt文件中 | |
ClearCnt : 接收计数清零,接收以字节计数,需要注意的是程序中的这个计数变量范围(防止溢出) | |
c 发送配置 | Hex / String : 以十六进制或是字符格式发送(预留,未实现) |
Clear : 清空发送框 f | |
Send : 将发送框 f 中的数据发送出去 | |
LoadSendText : 将.txt文件加载到发送框 f 中 LoadSendList : 将.txt文件加载到发送列表 d 中 需要注意的是,当加载到列表中时,.txt中的文本格式如下: cmdName1 cmdData1 cmdName2 cmdData2 cmdName3 cmdData3 cmdName4 cmdData4 一共8个字符串,每个占一行,当字符串少于8个时,缺少的将会以字符串“null”填充 |
|
SaveText : 将发送框 f 中的数据保存到.txt文件中 SaveList : 将发送列表 d 中的数据保存到.txt文件中 |
|
ClearCnt : 发送计数清零,发送以字节计数,需要注意的是程序中的这个计数变量范围(防止溢出) | |
ClearBeforeSend : 在发送前清空接收框 e,这个功能主要是用在单步发送时,有时我们会更关注本次发送数据后接收到的数据,避免上一次接收到的数据干扰分析 | |
d 发送列表 | 该功能主要用于某些固定协议的发送,在使用这部分功能时需要填写CmdData(发送的数据)、T(ms)(周期,term的缩写,单位为ms)、times(次数,正常情况下该值为大于0的值,若要一直发送,写入值为 -1,这里所谓的一直发送其实也是有限次,需要防止计数溢出),至于CmdName列不是必须的,只是为了增加发送数据的辨识,完成上述字段填充后勾选想发送数据,此时将会以固定周期,指定次数将数据发送出去,最底下的“0“处将显示剩余发送次数 这部分功能在程序中写的比较草率,主要是很多发送的协议是自定义的,需要根据具体的需求去实现,这里只是一个大概框架 |
e 接收框 | 用于显示接收到的数据 |
f 发送框 | 用于显示/写入发送的数据 |
g 状态框 | 当某些操作出错时,给用户一些提示,例如当打开某个串口时,如果该串口没有读写权限,将会提示”Permission denied“ |
5 移植到开发板
移植前本以为会很顺利,但在这部分内容上花了不少时间,首先保证程序在虚拟机上运行时没有问题,此时生成可供arm架构执行的文件,步骤如下图所示,点击“Build”后再点击“Build Project’xxx’for All Configurations”(也可在此操作前点“Clean”清除之前生成的文件),这将会在项目目录下生成/更新“build”文件夹中的文件,以本项目为例,完成上述操作后将便可将“…/build/armqt-Debug/03test”传到板子上运行
直接运行该文件在板子上报如下错误:
symbol lookup error: ./xxx: undefined symbol: _ZN20QTextStreamFunctions4endlER11QTextStream, version Qt_5
,这个报错信息令人一头雾水,不知所云,在网上查阅了大量资料后大致了解到这种错误主要是由于编译环境与运行环境不同造成的(准确来说是运行时链接的库有问题,可能是路径不对,可能是版本不对,也可能是使用不同编译工具造成的),由于上一篇文章写了一个控制风扇的小工具,那个工具可以正常运行,这说明路径以及版本啥的应该没问题,再由上边的报错信息来着,错误可能是由于QTextStream
造成的,编写的串口工具确实调用了#include <QTextStream>
,这里主要是用来对文件进行读写,为排除该问题,在程序中使用了另外的方法对文件进行读写,编译后再次运行该错误解决
然上面的报错解决后又出现了新的错误:
symbol lookup error: ./03test: undefined symbol: _ZNK7QString5splitERKS_6QFlagsIN2Qt18SplitBehaviorFlagsEENS3_15CaseSensitivityE, version Qt_5
,从报错信息提取有用的一丁点信息QString5split
,盲猜是split
这个函数的问题,于是在程序中使用了另外的方法对字符串进行处理,编译后运行错误解决,串口工具正常运行
此时在电脑与板子上各插入一个USB转串口模块(两个模块连接方式与前文相同)打开串口工具,点击“Search”,此时会搜索到对应串口,配置并打开,此时串口工具正常运行,至此串口工具移植到开发板上完成
在解决上边的问题时取了巧,使用了其他函数解决问题,问题虽然解决了,但并不完美,若下次遇到类似的问题,找不到合适的方法或是出现了大量类似问题,上述方法就不再适用,于是尝试在网上查找相关资料,详见脚注【d-e】,需要注意的是这两篇文章中的方法本人并未验证,仅供参考,另外该项目(串口工具)修复这两个问题前后的工程都会在文末仓库中给出,可自行下载对比
文件成功运行后便是创建一个快捷方式,这部分在前一篇文章中有详细介绍,这里不再赘述,本项目的相关资料都将在文末仓库中给出,有需要的可自行下载
【a】 Ubuntu使用串口时出现 Input/Output error提示
【c】 Linux/ubuntu下ttyUSB0等串口永久权限设置
【d】 undefined symbol: _ZdlPvm, version Qt_5错误以及error while loading shared libraries: xxx.so解析
【f】 undefined symbol: _ZdlPvm, version Qt_5错误以及error while loading shared libraries: xxx.so解析