串口是采用串行方式的通讯接口,串口中数据按位传送,最少只需一根传输线即可完成传输,这种特性决定了它的传输速率相对较慢且抗干扰能力较弱。
在实际应用中, 数据频繁的在上位机和下位机之间传输,如何提高传输效率,快速识别数据,保证数据的正确性和协议的易用性,是协议设计时主要考虑的因素。
1.如何提高传输效率
由于数据按位传输,在波特率一定的情况下,传输越少的数据耗时越少,因此可以通过减少每条数据的字节数来缩短发送和接收的时间从而提高传输效率,由于要减少数据长度,在协议灵活性上就睡有所损失。
2.如何快速识别协议数据
使用特殊字符可以快速识别数据包的开始位置,这个特殊字符也叫做帧头或协议头。协议头以后的字节都是数据包的内容,根据协议的长度通常有以下三种方式来识别数据包结尾:
a.固定协议,从接收到头后读取固定长度字节,字节数够了就认为数据包接收完了;
b.变长协议,使用固定字符结尾即协议尾,当读取到这个结尾字符时即表示数据包接收完了;
c.变长协议,在协议头后增加字节表示数据包长度,当接收满长度时即表示数据包接收完了;
不难发现,协议头和协议尾都是用来标识数据包的,应该使用不常出现的字符,当数据包中出现这种字符时应做响应的替换。
3.如何保证数据的正确性
数据包按字节在串口中传输,遇信号干扰或是线路问题很容易造成丢失或数据错误,可在发送前对关键数据进行签名并将签名结果与数据一起传输,对方收到数据后按照相同的签名规则计算签名结果并与数据包中的签名比较,如果一致则说明数据是正确的,常见的签名方式有MD5/CRC等,在串口通讯中CRC16或CRC32或者数据异或的方式进行校验。
从协议的灵活性上来说,通常我们会选择使用变长协议,结合上面说到的几点,就可以设计出一个协议框架了:
4.如何避免答非所问?
上下位机的通讯通常都是以问答模式进行的,如下位机问上位机现在几点了?上位机会立即回复当前的时间,当出现通讯故障或是处理延时就会出现请求堆积,当多条回复数据到下位机时,如何才能识别正确的回复呢?是的,可以增加通讯序号,当请求方发送数据时在协议中增加通讯序号,处理方返回数据时将通讯序号原样返回,请求方对比接收到的数据,如果通讯序号与发送时一致,则说明收到了正确的回复。
5.如何让协议更易用
按照上面几点设计出来的协议具有很强的通用性,使用时真实的业务都放在数据部分,当需要使用数据的时候都需要在数据完整解析以后才能使用,这在数据处理上会造成一定的浪费,其实对于自定义的协议来说,可以将一些通用数据放到数据外层,比如命令号,设备类型等,这样在做数据路由处理的时候会更省时。
虽然这是串口通讯协议设计的一些事项,但其设计的原理同样适用与TCP通讯。