SBUS使用

第一次接触S-BUS协议,踩了好多坑,在此记录一下。本人用的是stm32F429 + 普通航模遥控器(某宝上一大堆),用来遥控继电器,管脚自定义。

S-BUS协议

S-BUS其实是一种串口通信协议,采用100000的波特率,数据位点8bits,停止位点2bits,偶效验,即8E2的串口通信。但是S-BUS采用的是反向电平传输,也就是说,在S-BUS的发送端高低电平是反向的,协议中的所有高电平都被转换成低电平,协议中的所有低电平都被转换成高电平。所以在S-BUS的接收端需要增加一个高低电平反向器来进行电平反转。附上网上最流行的反相电路(可以自己买一个反相模块,3RMB左右)

SBUS使用_第1张图片

实际可行的电路,设计参考Pix Racer

SBUS使用_第2张图片

图为 Pix Racer 原理图

引脚功能描述

  • SBUS_INV -》SBUS输出使能
  • RC_INPUT -》外部SBUS/PPM信号
  • FMU_RC_INPUT -》MCU串口RX/PWM引脚
  • FMU_RC_OUTPUT -》MCU串口TX/PWM引脚

这里使用异或门电路,当SBUS_INV为高电平时,1Y/2Y的输出电平与1B/2B的输出电平相反; 当SBUS_INV为低电平时,1Y/2Y的输出电平与1B/2B的输出电平相同。因此可在代码中设置SBUS_INV脚的电平来配置串口转SBUS协议。

此外,在STM32中,若将 FMU_RC_INPUT、FMU_RC_OUTPUT 引脚接到可复用为串口和PWM通道的引脚上时,可在代码中设置引脚复用,从而使INPUT兼容SBUS、串口、PWM、PPM等多种通信协议。

改进

原工程中将2Y引脚串联470R电阻后接到 RC_INPUT 脚,这里可以将2Y脚另外接到一个RC_OUTPUT脚上,从而可以实现多种协议的同时输入输出功能。

此外,如果使用两个单路异或门电路可配置两个使能引脚,继而可以实现同时输入输出不同协议的飞控信号。

需要注意的是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
以此类推,如果还没明白可以参见视频,小姐姐讲的很明白呢!

SBUS使用_第3张图片

stm32解析S-BUS协议

利用stm32开发板解析S-BUS协议最重要有两点:

  1. 串口配置为100000波特率,8位数据位(stm32编程选9位),2位停止位,无硬件流控
  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;
}

你可能感兴趣的:(嵌入式软件,单片机)