R9DS接收机SMBUS数据解析

1常见模型控制信号

模型遥控器接收机输出的信号常见有三种:PWM、PPM、SBUS。

PWM信号优点是模型都有成熟的PWM控制的配套模块,如舵机、电调大部分都是PWM接口的,同样也存在很明显的缺点,第一是连线较多,每个通道至少需要1根线,第二是PWM信号是以高电平的时间作为控制信号,电平边沿容易受到干扰,造成错误的控制。

PPM可以理解成在一根线输出多组PWM信号,缺点显而易见和PWM信号一样,优点是少了不少线。

SBUS是两线制通信,需要信号线和地线即可,本质还是串口,此文重点介绍SBUS信号的电路、协议。

2 SBUS电路

SBUS电平本质是串口TTL电平,实质呢,电平和串口TTL是相反的,Futaba制定这个协议的时候有可能是为了规避专利,也有可能是为了装X……,给我们带来的问题就是需要电平转换电路,可以用2个电阻1个三极管实现,还用更简单的用1片74系列的单路反向芯片,本例中用的是三极管电阻方式,没有现成的板子临时搭个电路实验,本文以R9DS接收机、STM32F1XX测试,电路图、实物图如下:

       R9DS接收机SMBUS数据解析_第1张图片

                          电路原理图                                                  电路实物                                               反向效果图

OK,电路问题解决了,下面开始读取数据

3 接收数据

Futaba官网说的很清楚:

The protocol is 25 Byte long and is send every 14ms (analog mode) or 7ms (highspeed mode).
One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2), baudrate = 100'000 bit/s
The highest bit is send first. The logic is inverted (Level High = 1)

翻译出来是这样的:一帧数据由25个字节构成,低速模式周期为14ms,高速模式周期为7ms,1个字节有1个起始位8个数据位1个校验位2个停止位构成,波特率为100K,高位在前低位在后,注意:电平是反的。

串口配置如下:

  Uart_Init(COMM1,100000,USART_WordLength_8b, USART_Parity_Even);  

串口接收中断:

void SBUS_RX_ISR(void)

{
  INT8U res;
  static INT8U Rx_Sta = 0;

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    res =USART_ReceiveData(USART1);
    SbusRxBuf[Rx_Sta++] = res;
  }
  else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
  {
    USART_ReceiveData(USART1);
    Rx_Sta = 0;
  }
}

调试数据可以接收:

R9DS接收机SMBUS数据解析_第2张图片

4数据解析

接收的数据和通道值是怎么个对应关系呢,Futaba官网接收如下:

[startbyte] [data1] [data2] .... [data22] [flags][endbyte]

startbyte = 11110000b (0xF0)

data 1-22 = [ch1, 11bit][ch2, 11bit] .... [ch16, 11bit] (ch# = 0 bis 2047)
channel 1 uses 8 bits from data1 and 3 bits from data2
channel 2 uses last 5 bits from data2 and 6 bits from data3
etc.

flags = bit7 = ch17 = digital channel (0x80)
bit6 = ch18 = digital channel (0x40)
bit5 = Frame lost, equivalent red LED on receiver (0x20)
bit4 = failsafe activated (0x10)
bit3 = n/a
bit2 = n/a
bit1 = n/a
bit0 = n/a

endbyte = 00000000b

一帧数据由1字节起始字节0xf0,22字节的通道数据,1字节标志位,1字节结束字节构成,总共25个字节,22个字节可以传输22*8/11=16通道数据,数据范围为0-2047。标志位的用R9DS没测试出Futaba协议中介绍的含义,有可能协议不兼容。

,遥控器关闭没信号时候,SbusRxBuf[24]接收数据位0xc0,,打开遥控器有信号时,SbusRxBuf[24]字节为0x00,可以用来做失控判断。

16通道数据解析如下:

void Sbus_Data_Count(INT8U *buf)
{
  SbusCh[ 0] = ((INT16U)buf[ 1] >> 0 | ((INT16U)buf[ 2] << 8 )) & 0x07FF;
  SbusCh[ 1] = ((INT16U)buf[ 2] >> 3 | ((INT16U)buf[ 3] << 5 )) & 0x07FF;
  SbusCh[ 2] = ((INT16U)buf[ 3] >> 6 | ((INT16U)buf[ 4] << 2 )  | (INT16U)buf[ 5] << 10 ) & 0x07FF;
  SbusCh[ 3] = ((INT16U)buf[ 5] >> 1 | ((INT16U)buf[ 6] << 7 )) & 0x07FF;
  SbusCh[ 4] = ((INT16U)buf[ 6] >> 4 | ((INT16U)buf[ 7] << 4 )) & 0x07FF;
  SbusCh[ 5] = ((INT16U)buf[ 7] >> 7 | ((INT16U)buf[ 8] << 1 )  | (INT16U)buf[9] <<  9 ) & 0x07FF;
  SbusCh[ 6] = ((INT16U)buf[9] >> 2 | ((INT16U)buf[10] << 6 )) & 0x07FF;
  SbusCh[ 7] = ((INT16U)buf[10] >> 5 | ((INT16U)buf[11] << 3 )) & 0x07FF;
  SbusCh[ 8] = ((INT16U)buf[12] << 0 | ((INT16U)buf[13] << 8 )) & 0x07FF;
  SbusCh[ 9] = ((INT16U)buf[13] >> 3 | ((INT16U)buf[14] << 5 )) & 0x07FF;
  SbusCh[10] = ((INT16U)buf[14] >> 6 | ((INT16U)buf[15] << 2 )  | (INT16U)buf[17] << 10 ) & 0x07FF;
  SbusCh[11] = ((INT16U)buf[16] >> 1 | ((INT16U)buf[17] << 7 )) & 0x07FF;
  SbusCh[12] = ((INT16U)buf[17] >> 4 | ((INT16U)buf[18] << 4 )) & 0x07FF;
  SbusCh[13] = ((INT16U)buf[18] >> 7 | ((INT16U)buf[19] << 1 )  | (INT16U)buf[21] <<  9 ) & 0x07FF;
  SbusCh[14] = ((INT16U)buf[20] >> 2 | ((INT16U)buf[21] << 6 )) & 0x07FF;
  SbusCh[15] = ((INT16U)buf[21] >> 5 | ((INT16U)buf[22] << 3 )) & 0x07FF;
  yy = (INT16U)(0.6056*SbusCh[0]+895);
}

yy = (INT16U)(0.6056*SbusCh[0]+895);是y=ax+b的形式,实现SBUS数据与PWM脉宽的转换,转向系数a、b根据程序实际读到的数据和示波器读到的脉宽计算出来,就是个2点直线方程。

在10ms定时器中调用Sbus_Data_Count(SbusRxBuf);就可以计算出16个通道的数据,R9DS只能支持收到10个通道数据。

你可能感兴趣的:(模型)