最近搞了一段时间嵌入式,深觉行行不容易😭。。。。。第一次接触S-BUS协议,踩了好多坑,在此记录一下。本人用的是stm32F429 + 普通航模遥控器(某宝上一大堆),用来遥控机器人小车,管脚自定义。
S-BUS协议
S-BUS其实是一种串口通信协议,采用100000的波特率,数据位点8bits,停止位点2bits,偶效验,即8E2的串口通信。但是S-BUS采用的是反向电平传输,也就是说,在S-BUS的发送端高低电平是反向的,协议中的所有高电平都被转换成低电平,协议中的所有低电平都被转换成高电平。所以在S-BUS的接收端需要增加一个高低电平反向器来进行电平反转。附上网上最流行的反相电路(可以自己买一个反相模块,3RMB左右)
PS:一定要硬件取反,软件没用。我也不知道为什么╮(╯▽╰)╭
需要注意的是S-BUS中用11bits来表示一个遥控器通道的数值,22个字节就可以表示16通道(8 × 22 = 11 ×16)。11个bit可以表示的数值范围为0~2047。每帧25个字节,排列如下:
[start byte] [data0] [data1] [data2] [data3] ... [data10] [flag] [end byte]
附上网上最流行的解说图,简单来说就是
start byte = 0x0F
CH1 = [data0]的8位 + [data1]的低3位
CH2 = [data1]的高5位 + [data2]的低6位
... ...
end byte = 0x00
以此类推,如果还没明白可以参见视频,小姐姐讲的很明白呢!
stm32解析S-BUS协议
利用stm32开发板解析S-BUS协议最重要有两点:
- 串口配置为100000波特率,8位数据位(stm32编程选9位),2位停止位,无硬件流控
- 对收到的25字节数据解码(包括数据头0x0F)
#define SIZE_BUFF (100)//S-BUS协议中遥控器通道数值范围
//S-BUS解析函数
int sbus_read_parse(int _fd, uint16_t *val){
//读取遥控器通道数据
uint8_t _buf[SIZE_BUFF];
int len = read(_fd, _buf, SIZE_BUFF);
if (len < 0)
{
return -1;
}
//略过协议包头、包尾、长度判断过程
//按11bits解析遥控器通道
val[0] = ((buff[ind + 1] | buff[ind + 2] << 8) & 0x07FF);
val[1] = ((buff[ind + 2] >> 3 | buff[ind + 3] << 5) & 0x07FF);
val[2] = ((buff[ind + 3] >> 6 | buff[ind + 4] << 2 | buff[ind + 5] << 10) & 0x07FF);
val[3] = ((buff[ind + 5] >> 1 | buff[ind + 6] << 7) & 0x07FF);
val[4] = ((buff[ind + 6] >> 4 | buff[ind + 7] << 4) & 0x07FF);
val[5] = ((buff[ind + 7] >> 7 | buff[ind + 8] << 1 | buff[ind + 9] << 9) & 0x07FF);
val[6] = ((buff[ind + 9] >> 2 | buff[ind + 10] << 6) & 0x07FF);
val[7] = ((buff[ind + 10] >> 5 | buff[ind + 11] << 3) & 0x07FF);
val[8] = ((buff[ind + 12] | buff[ind + 13] << 8) & 0x07FF);
val[9] = ((buff[ind + 13] >> 3 | buff[ind + 14] << 5) & 0x07FF);
val[10] = ((buff[ind + 14] >> 6 | buff[ind + 15] << 2 | buff[ind + 16] << 10) & 0x07FF);
val[11] = ((buff[ind + 16] >> 1 | buff[ind + 17] << 7) & 0x07FF);
val[12] = ((buff[ind + 17] >> 4 | buff[ind + 18] << 4) & 0x07FF);
val[13] = ((buff[ind + 18] >> 7 | buff[ind + 19] << 1 | buff[ind + 20] << 9) & 0x07FF);
val[14] = ((buff[ind + 20] >> 2 | buff[ind + 21] << 6) & 0x07FF);
val[15] = ((buff[ind + 21] >> 5 | buff[ind + 22] << 3) & 0x07FF);
return 0;
}
!!友情提示!!
在查看收发数据的过程中,建议调式查看(从内存查看),本人利用串口调试助手查看了好久,结果五花八门,以为自己写错了,结果。。。。。所以,强烈建议直接查看内存数据!
[参考链接]
http://www.zhuanzhi.ai/document/320303c82aa1cdbd101cdf599f9212d8
http://www.jianshengdrlab.com/forum.php?mod=viewthread&tid=115
https://www.eefocus.com/taogashi/blog/14-05/303577_f140d.html
http://www.stmcu.org.cn/module/forum/thread-617048-1-1.html
https://github.com/MuJanFun/Hawk_A/tree/master/STM32F103%E5%BA%95%E5%B1%82/BSP
网友评论