遥控器协议解析—SBUS篇
1、SBUS信号解析
SBUS全称serial-bus,是一种串口通信协议,仅用一根信号线就能传输多达16通道的数据,比多路PWM捕获高效且省资源。
1.通信接口
USART(串口TTL)
2.串口配置
100k波特率(100 000 bits/s),8位数据位,2位停止位,偶校验(EVEN),无控流,25个字节。
(注:如果用单片机进行配置需把数据位配置成9位,否则读取无法解码)
3.协议格式
数据共25个字节
开始字节:startbyte=0x0f
通道数据字节:[data1][data2]…[data22]
data1~22: LSB(低位在前),对应16个通道(ch1-ch16),每个通道11bit(22 × 8=16 × 11);
标志位字节:[flags]
flag位标志遥控器的通讯状态,可以通过查询flag位来采取失控保护(例如乐迪R9Ds的flag位为0x00时标志存在连接)。
结束字节:endbyte=0x00
2、SBUS硬件反相器电路设计
接收机接在板子上必须加入硬件反相器,因为SBUS的信号是采用的负逻辑,也就是电平相反,只能在硬件上进行反相,在软件上无法操作。
硬件反相器设计如下:
3、程序实现
cubeide配置:数据位一定要设置为9位
需要注意的是HAL库串口中断一次后需要再开启中断才能进行下次中断
#define SBUS_DATA_SIZE 25 // 25字节
struct SBUS_t{
uint16_t ch[16]; // 16个字节数据
};
uint8_t sbus_rx_sta = 0; // sbus 接收状态,0:未完成,1:已完成一帧接收
uint8_t sbus_rx_buf[SBUS_DATA_SIZE]; // 接收sbus数据缓冲区
uint8_t connect_flag = flase; // 连接是否正常
struct SBUS_t sbus; // SBUS 结构体实例化
void SBUS_IT_Open(void)
{
HAL_UARTEx_ReceiveToIdle_IT(&huart4, (uint8_t *)sbus_rx_buf, SBUS_DATA_SIZE);
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance == USART6){
if ((sbus_rx_buf[0] == 0x0F)&&sbus_rx_buf[24]==0x00)
{
sbus_rx_sta = 1;
}
else
{
sbus_rx_sta=0;
}
if(sbus_rx_sta==1)
{
sbus.ch[0] =((sbus_rx_buf[2]<<8) + (sbus_rx_buf[1])) & 0x07ff;
sbus.ch[1] =((sbus_rx_buf[3]<<5) + (sbus_rx_buf[2]>>3)) & 0x07ff;
sbus.ch[2] =((sbus_rx_buf[5]<<10) + (sbus_rx_buf[4]<<2) + (sbus_rx_buf[3]>>6)) & 0x07ff;
sbus.ch[3] =((sbus_rx_buf[6]<<7) + (sbus_rx_buf[5]>>1)) & 0x07ff;
sbus.ch[4] =((sbus_rx_buf[7]<<4) + (sbus_rx_buf[6]>>4)) & 0x07ff;
sbus.ch[5] =((sbus_rx_buf[9]<<9) + (sbus_rx_buf[8]<<1) + (sbus_rx_buf[7]>>7)) & 0x07ff;
sbus.ch[6] =((sbus_rx_buf[10]<<6) + (sbus_rx_buf[9]>>2)) & 0x07ff;
sbus.ch[7] =((sbus_rx_buf[11]<<3) + (sbus_rx_buf[10]>>5)) & 0x07ff;
sbus.ch[8] =((sbus_rx_buf[13]<<8) + (sbus_rx_buf[12])) & 0x07ff;
sbus.ch[9] =((sbus_rx_buf[14]<<5) + (sbus_rx_buf[13]>>3)) & 0x07ff;
sbus.ch[10]=((sbus_rx_buf[16]<<10) + (sbus_rx_buf[15]<<2) + (sbus_rx_buf[14]>>6)) & 0x07ff;
sbus.ch[11]=((sbus_rx_buf[17]<<7) + (sbus_rx_buf[16]>>1)) & 0x07ff;
sbus.ch[12]=((sbus_rx_buf[18]<<4) + (sbus_rx_buf[17]>>4)) & 0x07ff;
sbus.ch[13]=((sbus_rx_buf[20]<<9) + (sbus_rx_buf[19]<<1) + (sbus_rx_buf[18]>>7)) & 0x07ff;
sbus.ch[14]=((sbus_rx_buf[21]<<6) + (sbus_rx_buf[20]>>2)) & 0x07ff;
sbus.ch[15]=((sbus_rx_buf[22]<<3) + (sbus_rx_buf[21]>>5)) & 0x07ff;
if(sbus_rx_buf[21] != 0x00)connect_flag = flase;
else connect_flag = ture;
sbus_rx_sta = 0; // 准备下一次接收
}
SBUS_IT_Open();
}
}