项目介绍:一个工业机器小车的控制软件,基于 rs485 协议,使用 Modbus 进行通信,功能包括操控小车的前进、后退、左右转、驱动器的开停机、使能、急停,具体功能的开闭。
项目难度
一般,功能也不复杂,对于初学者来说需要同时学习 CPP 知识和 QT 的基本知识,最主要的是理解和学习 modbus 通信,需要看懂硬件设备的开发手册。
QT 应该算是封装得比较好的 CPP 了,开发过程中没有使用到复杂的特性和指针用法,对于前端开发者(没有经常使用静态类型的 OOP 语言)来说,可能初始化列表、析构函数、访问权限修饰符等会比较陌生,其实还挺好上手的(我自己之前就捣鼓过 c#)。 当我看到 Lambda 表达式的时候,我发现很多语言其实都是互通的,我当时脑海中就冒出一句话:这不就是匿名函数嘛,我可太熟悉了。当然,你不能忽视它给你提供的捕获列表功能。
所以,开发者千万不要被语言所局限,它只是工具,而我们需要掌握的是它们背后的共同点————开发思想。
QT 的信号槽,前端开发者肯定又是非常地熟悉,connect
就是事件绑定,槽函数就是事件回调函数,QTimer 就是setTimeinterval
。整个开发流程下来,我能将所有的关注点放在业务逻辑上,这就是得益于 QT 的设计。(和项目复杂程序有关系,毕竟还没有用上多线程)。
难点
-
找到正确的指令。每一个动作都需要一个对应的指令,一开始我挺迷茫的,看到起始位、寄存器地址、16 位、高低位、CRC 校验码、16 进制等字样的时候我就知道我已经把大学学习的知识还给老师了(悲)。由于一开始没有拿到开发手册,一些指令都是硬编码,调试起来也挺困难,后续有了手册后仔细研究了下我也基本知道了哪个功能用哪个指令了。说到底,前两年一直都是从事前端开发的工作,顶层应用做多了,对于底层的知识那是真越来越模糊了,还是得再回去翻翻大学的课本。
-
项目模块设计。该项目规模不大,接手时也就两个 cpp 文件,但是基本所有的逻辑都挤在了
mainwindow.cpp
中,几千行的代码包括了信号连接、槽函数定义、串口通信、工具方法等,过于耦合,看得人头大。后续我抽离出设备类、串口管理类、Modbus 指令生成类、界面类、工具类进行解耦,看起来舒服多了,也更利于调试指令。 -
串口通信。有的动作是需要同时发送多个指令,但是串口是串行通信,这也就导致了沾包问题,后续通过维护一个队列配合定时器来进行发送解决了这个问题。由于小车车速是需要实时获取的,也就是说在设备连接开启后需要一直轮询发送读取指令,我第一次的做法是将读取操作独立出来,另开一个队列进行轮询,后面发现如果用户在进行其他操作时会出现指令丢失,这就是串口竞争的问题。最后的解决方法是只维护一个队列,对指令进行优先级划分,轮询读取指令低于其他指令,确保其他指令加入队列后永远插队在轮询指令前。
总结
-
项目模块划分需要确保低耦合高内聚
-
在 QT 中更推荐使用单例模式而不是手动
new
-
合理使用
enum class
-
UI 开发还得是 web
-
串口开发要多利用一些串口开发工具