1、简介
SBUS,全称Serial Bus,即串行通信总线。本质上是一种串口通信协议,采用100K的波特率,8位数据位,2位停止位,偶效验,即8E2的串口通信。
2、串口配置
100k波特率,8位数据位(在stm32中要选择9位),偶校验(EVEN),2位停止位,无控流,25个字节。
3、协议格式
[startbyte] [data1][data2]…[data22][flags][endbyte]
startbyte=0x0f;
endbyte=0x00;
flags标志位是用来检测控制器与px4是否断开的标志位:
flags=1:控制器与接收器保持连接;
flags=0:控制器与接收器断开(失控),px4会控制电机停转。
data1…data22:对应16个通道(ch1-ch16),每个通道11bit(22X8=16X11=176)
数据范围在0-2047之间,基本上是282~1722,中值为1002;
ch1的11位=data2的低3位+data1的8位;
例如:data1=00110110,data2=11001111;
这时ch1=111 00110110=1846;通道1 的值就为1846;
ch2=data3的低6位+data2的高5位;
ch3=data5的低1位+data4的8位+data3的高2位;
ch4=4 7;
ch5=7 4;
ch6=2 8 1;
ch7=5 6;
ch8=8 3;
ch9=1 8;
ch10=4 7;
ch11=7 4;
ch12=2 8 1;
ch13=5 6;
ch14=8 3;
ch15=3 8;
ch16=8 5;
4、取反问题
用stm32中给px4发时,需要取反,并且是硬件取反,软件取反是无效的;硬件取反的电路图如下。
5、间隔问题
它分两种模式(高速模式和普通模式)
高速模式:每隔7ms一帧数据,因为两帧的间隔只有超过3ms,才会被接受;
而根据波特率计算一下,发送25字节需要的时间+3~4ms=7ms
普通模式:每隔14ms一帧数据;
6、数据解析与合并
#include "Sbus.h" #include "bsp_usart1.h" #include "string.h" uint16_t values[16]={0}; void sbus_out(uint16_t num_values) { int i=0; uint16_t value=0; uint8_t byteindex = 1; uint8_t offset = 0; uint8_t oframe[25] = { 0 }; memset(oframe,0,25); oframe[0]=0x0f; oframe[24]=0x00; for (i = 0; (i < num_values) && (i < 16); ++i) { value = (unsigned short)(((values[i] - SBUS_SCALE_OFFSET) / SBUS_SCALE_FACTOR) + .5f); if (value > 0x07ff) { value = 0x07ff; } while (offset >= 8) { ++byteindex; offset -= 8; } oframe[byteindex] |= (value << (offset)) & 0xff; oframe[byteindex + 1] |= (value >> (8 - offset)) & 0xff; oframe[byteindex + 2] |= (value >> (16 - offset)) & 0xff; offset += 11; } for (i=0;i<25;i++) { while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET); USART_SendData(USART1, (uint16_t)oframe[i]); } } void sbus_decode(unsigned char *frame) { unsigned int pick=0,channel=0,value1=0,piece=0; const struct sbus_bit_pick *decode; for (channel = 0; channel < 16; channel++) { value1 = 0; for (pick = 0; pick < 3; pick++) { decode = &sbus_decoder[channel][pick]; if (decode->mask != 0) { piece = frame[1 + decode->byte]; piece >>= decode->rshift; piece &= decode->mask; piece <<= decode->lshift; piece &= 0x07ff; value1 |= piece; } } values[channel] = (uint16_t)(value1 * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET; if(channel==1) { values[channel]=3029-values[channel]; } } }
合成函数:
void sbus_out(uint16_t num_values);
//参数为通道数;
values[16]就是对应的16个通道;
解析函数:
void sbus_decode(unsigned char *frame);
//frame为25个u8位数据;