根据可能需要的功能以及所需的错误检查数量,有很多写入串行协议的方法。
在点对点协议中看到的一些常见的事情是:
讯息结束
最简单的ASCII协议,只是有消息字符序列的结束,往往\r
还是\n
因为这是当进入关键是什么会打印被击中。二进制协议可能使用0x03
或其他一些公共字节。
消息开始
仅具有消息结尾的问题是,当您发送消息时,您不知道还接收了哪些其他字节。这些字节然后将被添加到消息的前缀,并导致其被错误地解释。例如,如果Arduino刚从睡眠中醒来,则串行缓冲区中可能会有一些垃圾。为了解决这个问题,您需要先启动消息序列。在您的示例中,^
通常采用二进制协议0x02
错误检查
如果消息可能被破坏,我们需要进行一些错误检查。这可能是校验和或CRC错误或其他错误。
转义字符
可能是校验和添加到控制字符上,例如“消息的开始”或“消息的结束”字节,或者消息包含等于控制字符的值。解决方案是引入转义字符。转义字符放置在修改后的控制字符之前,因此实际的控制字符不存在。例如,如果起始字符为0x02,则使用转义字符0x10,我们可以在消息中将值 0x02作为字节对0x10 0x12(字节XOR控制字符)发送
包数
如果邮件已损坏,我们可以请求重新发送,其中包含nack或retry邮件,但是如果发送了多封邮件,则只能重新发送最新的邮件。相反,可以为数据包提供一定数量的消息,该消息将在一定数量的消息后翻转。例如,如果此数字为16,则发送设备可以存储最近发送的16条消息;如果有任何消息损坏,则接收设备可以使用数据包号请求重新发送。
长度
通常在二进制协议中,您会看到一个长度字节,该字节告诉接收设备消息中有多少个字符。这就增加了另一级错误检查,好像没有收到正确的字节数,那么就出现了错误。
特定于Arduino
在为Arduino提出协议时,首先要考虑的是通信通道的可靠性。如果您通过大多数无线媒体,XBee,WiFi等进行发送,则已经内置了错误检查和重试功能,因此将这些内容放入协议中毫无意义。如果您要通过RS422发送几公里,则很有必要。我将要包括的内容是消息的开头和结尾的字符。我的典型实现如下所示:
>messageType,data1,data2,…,dataN\n
用逗号分隔数据部分可简化解析,并且使用ASCII发送消息。ASCII协议很棒,因为您可以在串行监视器中键入消息。
如果您想要二进制协议(可能是为了缩短消息大小),则如果数据字节可以与控制字节相同,则必须实现转义。对于需要全面的错误检查和重试的系统,二进制控制字符更好。如果需要,有效负载仍可以是ASCII。