软件详解
本项目基于标准库编写,为了节约主控芯片Flash,采用了裸机编程且只导入了必要的文件,从而减少程序体积。下面将对本项目涉及的核心业务逻辑及其他关键代码进行说明。
注:本项目下位机代码完全开源,可在附件中自行下载“ComHubProject.zip”文件,代码进行了详细的注释便于理解。
开源链接:https://oshwhub.com/heyh/comportnumber-visualization-hub?
1、主从机交互
本项目的核心是通过主机发送电脑端的COM号检测从机CH344芯片所对应的COM号。
主从机先进行TCP建立连接后在通过UDP检测COM号。详细过程如下:
(1)TCP
第一次握手:从机上电后会自动初始化,并持续发送请求给主机,目的是判断主机是否在线。这个步骤确保从机知道主机的状态,防止从机在主机离线时浪费资源。
第二次握手:主机收到从机的请求后,响应从机的请求,通知从机主机现在已经在线,并且可以随时进入COM口扫描阶段。这一步确认了主从机之间的连接,确保从机在主机准备好后才会进入下一阶段。
第三次握手:从机在收到主机的响应后,会先关闭串口的接收中断,然后再向主机发送确认信息,表示从机已经准备好进入COM口扫描阶段。关闭接收中断可以防止在这个阶段收到其他无关的信号,从而避免干扰。
(2)UDP
在进入COM口扫描阶段后,主从机的通信方式切换为UDP,这样可以利用UDP的高效性来快速传输数据。主机通过轮询的方式不断发送CH344芯片对应的四个COM口的信息,从机则采用超时机制来判断这四个通道分别对应的电脑端的COM口。
(3)通信协议
| 帧头 | 数据长度 | 功能码 | 数据 | CRC8校验 | 帧尾 | |
| 从机发送com口检测请求 | B5 | 02 | 01 | 00 | XX | 5B |
| 主机响应 | A5 | 02 | 01 | 00 | XX | 5A |
| 从机响应 | B5 | 02 | 02 | 00 | XX | 5B |
| 主机轮询检测com口 | A5 | 02 | 02 | PC端com端口号 | XX | 5A |
| 从机发送通信停止信号 | B5 | 02 | 03 | 00 | XX | 5B |
虽然本项目需要通信的内容较为简单,但使用标准的通信格式依旧是十分有必要的,这是由于在串口轮询接收/发送时,会使用模拟开关将不使用的三路串口接地,这会导致RX信号线有一个下降沿信号,从有概率而误发送一个“无用”的字节到上位机,而如果不使用通信协议就会造成这个无用字节会被上位机接受影响正常通信。
(4)Q&A:
①为什么要同时用到TCP和UDP?
TCP的可靠性:在主从设备建立连接的初期,双方都需要确认对方在线并准备好进行通信。TCP提供了可靠的连接,确保数据的完整性和传输顺序。在通信开始前,建立一个稳定的TCP连接可以避免数据丢失和误判,这是非常重要的。
UDP的高效性:在COM口检测阶段,通信的需求是快速且无状态的。UDP比TCP更轻量级,并且没有复杂的握手过程,这使得它非常适合在短时间内快速发送和接收数据。由于UDP没有重传机制,它更适合用于那些即使数据包丢失也不影响整体工作的场景,比如在COM口扫描中,主机不停地轮询并发送数据,而从机只需要接收数据即可。
综上所述,在项目的不同阶段使用不同的通信协议可以充分发挥两者的优势:TCP用于确保连接的可靠性,UDP用于高效的数据传输。
②为什么不使用两次握手?
两次握手的风险:在两次握手的情况下,主机可能在从机还未完全准备好时就开始进行COM口扫描。这会导致主机的扫描数据未被从机正确接收,进而导致数据的误判。三次握手的第三次确认,从机可以明确通知主机它已准备好进行COM口扫描,避免了主机与从机之间的状态不同步问题。
从机的状态切换:从机在进行第一次握手时可能还在处理其他任务,如轮询多个通道。在这种情况下,如果直接进入COM口扫描,可能导致从机的状态切换不及时,进一步加大误判的风险。
三次握手的设计确保了主机和从机在同一个状态下开始COM口扫描,避免了潜在的同步问题和误判。
③为什么不通过延时解决问题?
时间的不确定性:在嵌入式系统中,不同设备之间的时间同步非常困难。即使主机在响应后延时进入COM口扫描模式,也无法保证从机在相同的时间窗口内进入扫描模式。这种时间上的不确定性可能导致主机和从机之间的同步问题,进而导致通信错误。
从机的超时机制:从机在COM口检测中使用了超时错误计数机制。如果从机比主机提前进入扫描模式,可能会由于等待主机的数据而触发超时机制,导致从机误判。
因此,依赖时间的方式无法保证可靠的通信,相比之下,使用三次握手的设计可以更加精确地控制主从设备的状态同步,确保通信的可靠性。
总结:该设计方案充分利用了TCP的可靠性和UDP的高效性,通过三次握手机制保证了主从设备的状态同步和数据传输的准确性。这种设计是合理且有必要的,能够有效避免误判和通信错误。
2、串口超时接收
在串口通信中,超时接收是一种有效的方法,用于处理数据接收不完整的情况。常见的应用场景有以下两种:
(1)固定长度数据:如果发送方因故未能完成一帧数据的发送,接收方需通过超时机制判断数据是否完整,以避免系统资源浪费。接收方设定一个超时值,如果在此时间内没有接收到更多数据,则认为当前数据帧接收结束。
(2)不定长度数据:对于数据长度不固定且没有明确帧尾的情况,接收方难以判断数据是否接收完整。通过超时机制,接收方可以监控数据长度的变化,若数据长度在一定时间内保持不变,则认为数据接收已经完成。
在本项目中,我们分别实验了使用软件定时器和硬件定时器配合标志位的方法。实验结果表明,硬件定时器与标志位的组合效果更佳,这表明串口超时接收对精度的要求较高。接下来介绍几种在项目中常用的定时机制。
3、定时机制
(1)软件定时器:软件定时器依赖于硬件定时器提供的时基单元,如滴答定时器。它在系统调度的基础上管理定时任务,虽然精度较高,但受系统负载影响,可能会有微小的调度延迟。软件定时器的实现可以通过在硬件定时器中每产生一次中断时,让全局变量加1,并在主程序中通过比较上次计数值和本次计数值来判断是否达到定时时间。然而,这种方法较为繁琐,每个定时任务都需要一个标志位。为了简化定时器管理,可以使用MultiTimer v2,它通过超时时间排序链表,提供更优雅的定时任务管理。详细移植过程可以参考链接[MultiTimer v2移植过程]。
(2)硬件定时器和标志位:硬件定时器与标志位配合使用能够显著提高定时精度。定时器产生中断,改变全局标志位,主程序检测到标志位变化后执行相应操作。这种方式具有较高的精度,适合对定时要求严格的应用,如本项目中的串口超时接收。
(3)硬件定时器输出捕获功能:硬件定时器输出捕获用于高精度定时任务,能够精确到微秒级别。当输出捕获中断触发时,会立即执行相应的回调函数。尽管精度极高,本项目由于资源限制,使用了前两种定时机制来满足定时需求。
4、按键驱动模块
在以往的项目中,我通常会自行实现基于定时器和状态机的软件消抖方案。但为了提升开发效率,这次选择了一个小巧、简单易用的事件驱动型按键驱动模块——MultiButton。MultiButton模块通过事件驱动的方式管理按键输入,自动处理消抖以及多按键组合问题。
相比于传统的基于状态机的软件消抖方案,这种模块化的设计能够简化代码结构,减少调试时间,并显著提高系统的灵活性和可靠性。由于MultiButton模块内置了成熟的消抖算法和按键事件处理机制,开发者无需再为这些基础功能编写复杂的代码,从而可以将更多精力投入到项目的核心逻辑开发上。
关于MultiButton模块的详细移植过程,可参考链接:[MultiButton移植过程] 。
5、UI交互
本项目中的UI显示起到了核心的功能,用户每次使用本设备最终的就是通过查看屏幕了解COM号,因此本项目的UI经过重点优化,特别是其中的字库以及显示部分
本项目从表面上看使用了1608和2412两个字库,实际上这两个字库都经过了特殊处理,因此本项目实际上包括了5套字库:1608特殊字库(只包括“C、O、M”三个字母)、2412数字字库、2412大写字库、2412小写字库、2412符号字库,他们均取模于不同的电脑字体。
其中1608特殊字库的“#¥%”三个特殊符号的字模被替换位“COM”对应的字模,字库剩余部分被删除用以节省flash空间。
由于单片机使用的是等距字体,在显示i或者小写的L这种特别细的字体时,以及显示M或者W这种特别宽的字体时,可能会造成整体观感不佳,另外需要注意的便是大小写、英语数字混合显示的情况下,需要进行一些微调获得更好的显示效果,因此本项目涉及UI显示部分的代码比较复杂。
上图为UI显示部分代码截图,其中展示了对部分字符位置进行的微调。
注:本项目是本人第一次做字体库,由于并没有找到系统性的教程,主要还是自己摸索加多次尝试做出来的,字体库做的并不是很好,因此才需要在UI代码里进行微调,后续项目进行时将重新制作一套字体库便于进行使用。待字体库使用熟练后,会考虑做一套非等宽字体获得最佳显示效果。
彩蛋:本项目UI配色参考了国际知名大厂的配色方案,发现的朋友可以写在评论区
6、主机(上位机)检测
上位机基于Python编写,已生成exe文件,请在附件中下载。
上位机的核心逻辑围绕串口设备的检测、配置和通信展开。上位机程序程序会扫描系统中的所有串口设备,查找描述信息中包含指定字符串(目前设定为“CH344”)的串口。如果找到符合条件的串口,程序会检查这些串口的制造商是否一致,以确保设备间的兼容性和通信的可靠性。
找到符合要求的串口后,程序配置通信参数,并进入轮询通信的循环。主机等待从机发送请求信号(功能码为0x01),收到请求信号后,发送响应帧并清空串口的接收缓冲区。接下来,主机等待从机发送启动信号(功能码为0x02)。启动信号到达后,主机开始在四个串口之间进行轮询通信。
在轮询过程中,每个串口依次发送包含功能码和端口编号的数据帧,其他串口接收数据并验证其有效性。如果接收到的帧中包含停止信号(功能码为0x03),通信终止,程序退出。整个过程中,CRC8校验算法保障了数据的完整性。
这一逻辑设计使程序能够有效地管理多个串口设备之间的通信,确保数据传输的准确性和一致性。
项目复刻注意事项
1、外壳文件可以建议3D打印,上面板建议采用亚克力激光切割加工,亚克力厚度为1.8mm。项目需要用到的3D文件、亚克力切割DXF文件均在项目附件,请自助下载。注:很多淘宝店铺标注2mm的亚克力,实际厚度就是1.8-1.9mm,请联系客服确认。
2、在项目复刻时,建议使用探针烧录,如果焊接了调试插座,则需要在安装设备外壳前取下,取下时可采用先用尖嘴钳拔出插座的塑料外壳,再逐一取下或剪断连接针,否则调试接口插座会与上面板压克力发生结构干涉。
3、特殊元器件、结构件采购链接,请注意规格:(非广告,仅供参考)
硅胶按键 分类:5.2H 注:项目工程中选用了高度5mm的“TS-1158UB-C-D-BL”按键,是因为立创商城中最高的硅胶按键就是这个型号了,自行复刻时为了更好的手感建议使用5.2或5.5头高的
M2支撑铜柱 分类:M2*2.5*3
顶板小头螺丝 分类:M2*3.5*3头径
底板沉头螺丝 分类:M2*5发黑
4、PCB上有六个圆孔,其中3个是直径2.1mm的M2螺丝固定孔,PCB的对角线的两个是用于经济型SMT的1.152mm专用定位孔,若不使用经济型SMT则可以根据实际情况删定位孔并重新铺铜。
其他
本项目使用的CH344Q芯片原生支持RS232/485,若您完全没有ttl串口需求,可以直接修改主板使得其支持232/485通信而不需要使用扩展板。
基于当前版本的软硬件,一台电脑仅能连接一个可视化串口集线器。后续如果对“更多串口”需求人数较多,可能会出USB转8串口的版本。
扫码加入QQ群3群| 610403240
280