-
首先我们要定义三个特殊字符:帧起始标志SOF,用0x7d表示;帧结束标志EOF,用0x7e表示、转义标志ESC表示0x7f。数据帧封装格式如下表所示:
串口链路层帧格式
| 域名称 | 描述 |
|---|---|
| SOF | 帧起始标志,固定为0x7d,SOF是Start of Frame的英文编写 |
| DATA | 要传输的数据,串口数据建议在512字节以内为宜 |
| EOF | 帧结束标志,固定为0x7e,EOF是End of Frame的英文缩写 |
-
由数据帧的封装格式中可以看出,0x7d和0x7e是帧的起始和末尾标志,那要是DATA中要传输0x7d和0x7e怎么办呢,这就需要进行转义了,我们定义了一个转义字符ESC,用0x7f 表示。当发送数据时,需要将数据域中的0x7d用0x7f 、0x00两字符替代、这就是所谓的转义,同样的,发送方将数据中的0x7e转义为0x7f、0x01,将0x7f转义成0x7f、0x02。对于接收方可以按照这样的规则对数据进行还原。转义字符表总结如下:
0x7d –>> 0x7f、0x00 0x7e –>> 0x7f、0x01 0x7f –>> 0x7f、0x02
以上两点就是链路层的规则,规则虽然简单,但是对于组帧却非常有用,而且不会产生歧义。
样例一: 应用层发送数据:0x55 0x66 0x88 0x99
数据经过链路层之后,实际发送数据:0x7d 0x55 0x66 0x88 0x99 0x7e
从这里可以看出,接收方根据起始标志0x7d和末尾标志0x7e很容易提取出实际数据0x55 0x66 0x88 0x99
样例二 应用层发送数据:0x55 0x7d 0x88 0x99
数据链路层发送数据:0x7d 0x55 0x7f 0x00 0x88 0x99 0x7e
这里可以看出,应用层发送数据中是包含了起始标志0x7d,但是在链路层就被转义成了0x7f、0x00,接收方连续收到0x7f、0x00就能还原为0x7d。
样例三 应用层发送数据:0x55 0x7f 0x00 0x99
数据链路层发送数据:0x7d 0x55 0x7f 0x02 0x00 0x99 0x7e
从上面三个例子中可以看出,发送的数据帧的数据域中是不可能出现0x7d和0x7e这两个字符的,因为链路层已经对它进行了转义,所以接收方一旦接收到0x7d就可以断定这是一帧的开始,接收到0x7e就表示一帧的结束,而0x7d与0x7e之间的数据就是发送方的数据内容,接收方需要在链路层将被转义的字符还原,然后再提交给应用层。
这么一来,就解决了数据成帧的问题。串口之间的通讯由面向字节通讯变成了面向帧的通讯,也就是说应用层数据不再是以字节为单位,而是以帧为单位。好比单片机发送一帧100字节的数据给PC,PC应用程序接收的便是一帧100字节的数据了。