SBUS协议在硬件上是串口反相协议。
在软件上就是普通串口协议,波特率100k,8位数据位,2位停止位,偶校验even。注意,stm32把校验位也当做数据,所以数据位要设置成9,而不是8。
其报文格式为:
字段 | 内容 |
头 | 定值0x0F |
通道值 | uint8[22] |
标志位 | uint8 |
尾 | uint8 |
SBUS协议总共可以携带16个通道的数据,每个通道的数据为11比特,那么16个通道共有16*11=176个比特。这176个比特,就存储在上述表格uint8[22]这个数组中。你会发现这个数组恰好能容纳22*8=176个比特。
下面的问题就是,每个通道的值是如何在这个数组中排布的。
基础知识,串口字节协议是低位(LSB)先发,例如某个字节值为0x8F(也即1000 1111),那么接收端按照先后顺序,依次收到的比特为:1 1 1 1 0 0 0 1。
刚开始感觉SBUS协议的通道值的拼凑规则非常奇葩,后来才理解到,它是完全按照串口硬件发送比特的顺序,来拼凑通道值的。先发送的11个bit就是通道0的值,接下来的11bit就是通道1的值,再接下来的11bit就是通道2的值。。。以此类推。而且通道值的拼凑也是按照串口的硬件规则来的,也即先收到的bit是最低位。
网上找了很多SBUS的图解,都做的不好,下面是我自己画的一个图,绝对清晰明了。
本文由【暴躁的野生猿】发表于CSDN,如有非法转载,请帮忙举报谢谢。
百度搜索:【暴躁的野生猿 CSDN SBUS协议解析图解】 可以找到原文。
下面表格第一行是串口通道值数组byte0~byte21共22字节,第二行是解析后通道值ch0~ch15共16个通道。
通道2的值横跨3个字节,我们以它为例:
uint16_t high = byte[4] & 0x01;//提取通道2的高1比特
uint16_t mid = byte[3] & 0xFF;//提取通道2的中间8比特
uint16_t low = (byte[2] >> 6) & 0x03;//提取通道0的低2比特
ch[2] = (low) | (mid << 2) | (high << 10);//得到通道2的值
如果有些通道只横跨2个字节,那么就不需要拼凑mid了,为了使程序更具通用性,可以&0x00。
更进一步,使用循环来解析16个通道,我们可以把上面程序中的出现的9个参数定义成结构体,一把就给解析出来,在ch2这个例子中,依次出现的9个参数为:
4、 0x01、 3、 0xFF、 2、 6、 0x03、 2、 10
按照这个规则,我们把16个通道的参数都写出来,存到结构体数组中,就可以一次性把16个通道值都解析出来了。