您好、欢迎来到现金彩票网!
当前位置:2019全年资料大全 > 通信协议 >

嵌入式硬件通信接口协议-UART(四)设计起止式的应用层协议

发布时间:2019-05-21 16:00 来源:未知 编辑:admin

  串口实现了两个终端设备之间进行可靠的通信,串口在这中间完成了传输层的作用。本次要讲的是关于数据的协议。

  在战争题材影视剧中经常能够看到这样的对白,在通过对讲机等相关无线设备呼叫队友时,先呼叫对方名称,然后告知自己身份,说完内容最后再说over,表示一次呼叫结束。

  UART的时序本身就是起止式协议,具体可参考《嵌入式硬件通信接口协议-UART(一)协议基础》这一篇内容的介绍。

  事实上串口实现了数据通信过程中的传输层,而应用层就系统功能的业务逻辑,应用层控制需要收发的各种数据内容。

  数据解析的前提是通信双方都是用统一的数据帧格式,因此在这里将设计一个简单的起止式的数据帧格式,保证设备之间进行可靠的通信。

  现在的很多无线模块,为了使用简单和易于集成,模块对外使用UART接口,并采用AT指令来完成配置和使用,常见的有ESP8266的WiFi模块、HC-05蓝牙串口模块。

  AT指令的特点是易于人机交互,使用者对其发AT指令时,都是用ASCII字符发送,对于模块的处理,也是以字符来处理。这样的AT指令,它的起止式特点是以“AT”两个字符开头,并以回车换行“”字符结束。

  但是项目工程中,数据在嵌入式设备是以HEX数据(16进制)运算和处理,如果参考AT指令去设计帧结构,那么在收发处理时候,必然要将收到的纯数据(16进制)按照字符处理。

  比如一个终端设备,其功能就是环境检测,可能包含温湿度、光照强度、二氧化碳浓度、PM2.5浓度等等,如果要发出一个温度采集结果24℃数据,采集设备将数据24分成2个字节发送,因为ASCII字符’2’对应的16进制是0x32、ASCII字符’4’对应的16进制是0x34,这样的一个温度数据就需要2个字节来发送。接收端接收到的是0x32、0x34后,再以查表方式逆向换算出原温度数据’24’,这个过程就是采用字符处理的麻烦之一。

  在一长串的数据流中,接收端逐字节接收,并判断是否存在0x55,如果存在则开始存入数据包缓冲器,直到接收了0xAA数据,认为完成一帧数据的接收。

  而这样存在很大的问题,如果传输的内容也有0xAA这样的数据,这个0xAA并非结尾标志,而程序接收过程就提前结束,这样就不能保证完整接收一帧数据包了。

  这样一来,接收端判断接收到了0x55的开头标志,紧接着再接收一个“长度”的字节,基于这个长度来继续接收后续剩余的数据。

  这样的接口,即使有开头、长度、结尾,还存在风险。比如传输数据时,物理线路受到未知干扰,导致数据内容出现了异常,那么接收端即使完整接收所有数量的数据下来,也是错误的内容。

  解决在发送过程中出现的未知错误问题,必然需要对数据进行校验。再增加一字段来标志数据内容的校验计算结果。

  校验值是对数据包采用算法计算而得,接收方完整收下所有数量的数据,再对数据包采用同样的算法计算出校验值,从而对比校验值来确定数据包的准确性。

  综上所述,基于起止式的帧结构可以设计成:0x55 + 长度 + CRC校验 + 数据包。

  0x55二进制是01010101,这样在UART物理线路上输出的信号将会是占空比50%的方波,方波是最容易进行测量和诊断的,在实际波形观测时可以确定稳定性、噪声毛刺等。

  要说0xAA(二进制10101010)也是可以,但是UART发送时候是有一个起始位0,并且是以LSB方式先发送bit0的最低位,0xAA的bit0已经是0,而0x55的bit0是1,因此想得到方波当然优先考虑用0x55。

  长度采用一个字节表示,则后续的CRC校验 + 数据包的总数量最多能放255个字节。

  CRC校验采用CRC-16算法,占2个字节,此时后续的数据包最多能放253个字节。

  packet数据包最大长度设为253,是因为len是uint8_t类型,len最大255,而CRC校验值占了2个字节,因此packet数据包最多可253个字节。

  CRC校验值采用的是CRC-16标准,校验值是个uint16_t类型的数据,传输时采用的是LSB模式,因此将CRC校验值设为两个uint8_t类型的数据,这样做便于在源码移植过程中,不同平台的大小端差异能够得到正确处理。

  计算后得到某一次的校验值结果是 0xDC66,这是一个uint16_t类型的数据,如果直接使用这个结构体来处理数据发送,那么:

  因此采用2个字节uint8_t数据类型代替uint16_t来定义结构体中的CRC校验值,使得在跨平台收发数据时无需做差异化处理。

  使用起止式进行数据传输时,把应用层的数据包进行组帧,这样可构造一个完整的数据帧,便于在应用层将完整的一帧数据传递给传输层发出。

  为了防止应用层调用接口时,传进来的数据包的地址、组帧结果的首地址指向同一个内存地址,所以在组帧前需要将源数据内容单独缓存,再进行“填充”的操作。

  这里被解析的数据来源是一个循环缓冲区,对循环缓冲区内的可读数据进行解析。因此需要使用循环缓冲区配合。

http://monsterbot.net/tongxinxieyi/2.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有