SBUS无线遥控STM32解码

发布时间:2023-03-23  

老规矩,先上效果,这是基于STM32F103C8T6解码出来的效果,遥感对应的是每个通道的值,一个遥感相当于对应4个数据通道,两个就是对应8个数据通道,而按钮则是最后一个通道,其它的通道是作为整个协议的备用通道,不同的遥控,实际能用的通道数不一样。

动图封面

说明:部分程序和资料整理于网络平台,由于时间久远,找不到原始发文地址,这里向贡献这些资料的大佬们致敬 。

SBUS协议:

SBUS是FUTABA提出的舵机控制总线,全称Serial Bus,别名S-BUS或SBUS,也称 Futaba SBUS。它就是基于串口反电平逻辑的传输方式。

通信接口:USART(TTL)

通信参数设置:100Kps, 8E2(8位数据位,偶校验,2位停止位,无流控)

每帧25个字节,帧格式如下


[Start Byte] [Data0] [Data1] …. [Data21] [Flags][End Byte]

Start Byte= 0x0F,中间22个字节为16个通道的数据,每个通道用 11 bit表示,范围是0-2047。

End Byte:根据SBUS协议版本不同而不同。

因为遥控接收模块出来的电平信号跟普通串口逻辑是反逻辑,所以还需要下面这个电平转换电路

遥控接收模块反逻辑电平电路

我手里头的这款遥控型号:风迎M11,2017年底购买的,价格接近上千大洋,现在价格要好很多了,不到1/3之一的价格就可以拿到。传输距离一般有6公里左右,搭配远距离图传模块做一些远程遥控操作用。当时为了解码sbus过来的数据在网上找了不少资料,但是发现arduino的能用,STM32的没有一个完整的程序,所以只能参考sbus协议的代码,然后再结合arduino能工作的程序,分析串口传输过来的数据,一个一个去调整串口的配置。

下图是该遥控模块的接收模块,双天线和数据通道冗余,确保接收数据的可靠。

arduino接收程序

我们先使用arduino看下模块以及我们对协议的理解正确与否,验证没有问题后,稍后我们在移植到STM32上面去。

动图封面

使用的是MEGA2560板子,反电平电路参考上面的电路连接,SBUS接收数据端口是19号引脚,也就是该板子的串口1,arduino软件安装完后自带的串口库,如果使用其它的arduino板子,请参考网上其它教程。

arduino串口参数设置:Serial1.begin(100000,SERIAL_8E2);

这部分代码是将接收到的串口数据进行解码,因为每个通道是11位数据,所以需要进行数据合成。

void update_channels(void)

{

  channels[0]  = ((sbus_data[1]|sbus_data[2]<< 8) & 0x07FF);

  channels[1]  = ((sbus_data[2]>>3|sbus_data[3]<<5) & 0x07FF);

  channels[2]  = ((sbus_data[3]>>6|sbus_data[4]<<2|sbus_data[5]<<10) & 0x07FF);

  channels[3]  = ((sbus_data[5]>>1|sbus_data[6]<<7) & 0x07FF);

  channels[4]  = ((sbus_data[6]>>4|sbus_data[7]<<4) & 0x07FF);

  channels[5]  = ((sbus_data[7]>>7|sbus_data[8]<<1|sbus_data[9]<<9) & 0x07FF);

  channels[6]  = ((sbus_data[9]>>2|sbus_data[10]<<6) & 0x07FF);

  channels[7]  = ((sbus_data[10]>>5|sbus_data[11]<<3) & 0x07FF); // & the other 8 + 2 channels if you need them

  #ifdef ALL_CHANNELS

  channels[8]  = ((sbus_data[12]|sbus_data[13]<< 8) & 0x07FF);

  channels[9]  = ((sbus_data[13]>>3|sbus_data[14]<<5) & 0x07FF);

  channels[10] = ((sbus_data[14]>>6|sbus_data[15]<<2|sbus_data[16]<<10) & 0x07FF);

  channels[11] = ((sbus_data[16]>>1|sbus_data[17]<<7) & 0x07FF);

  channels[12] = ((sbus_data[17]>>4|sbus_data[18]<<4) & 0x07FF);

  channels[13] = ((sbus_data[18]>>7|sbus_data[19]<<1|sbus_data[20]<<9) & 0x07FF);

  channels[14] = ((sbus_data[20]>>2|sbus_data[21]<<6) & 0x07FF);

  channels[15] = ((sbus_data[21]>>5|sbus_data[22]<<3) & 0x07FF);

  #endif

  // Failsafe

  failsafe_status = SBUS_SIGNAL_OK;

  if (sbus_data[23] & (1<<2))

  {

    failsafe_status = SBUS_SIGNAL_LOST;

  }

  if (sbus_data[23] & (1<<3))

  {

    failsafe_status = SBUS_SIGNAL_FAILSAFE;

  }


}

下面这部分代码是按照sbus的通信协议接收数据并缓存到缓冲区,判断接收到的数据是0x0f,则开始缓存数据,一直到缓冲完所有通道才结束,这里没有进行结尾检测影响不大,因为不同的接收模块结尾不一样,具体项目应用还请加上数据结尾检测。


void feedLine( void )

{

    if( Serial1.available()>24 )

    {

            while(Serial1.available()>0)

            {

                    inData = Serial1.read();

                    switch (feedState)

                    {

                    case 0:

                        if(inData != 0x0f)

                        {

                            while( Serial1.available()>0 ) 

                            {

                                inData = Serial1.read();

                             }

                            return; 

                         }

                         else

                         {

                              bufferIndex = 0;

                              inBuffer[bufferIndex] = inData;

                              inBuffer[24] = 0xff;

                              feedState = 1;

                          }

                          break;

                     case 1:

                         bufferIndex ++;

                         inBuffer[bufferIndex] = inData;

                         if (bufferIndex < 24 && Serial1.available() == 0)

                         {

                              feedState = 0;

                          }

                          if (bufferIndex == 24)

                          {

                              feedState = 0;

                              if (inBuffer[0]==0x0f && inBuffer[24] == 0x00)

                              {

                                  memcpy(sbus_data,inBuffer,25);

                                  toChannels = 1;

                              }

                          }

                         break;

                     }

//                     if (inData == 0x0f)

//                     {

//                         bufferIndex = 0;

//                         inBuffer[bufferIndex] = inData;

//                         inBuffer[24] = 0xff;

//                     }

//                    else

//                    {

//                          bufferIndex ++;

//                          inBuffer[bufferIndex] = inData;

//                    }

//                    if(inBuffer[0]==0x0f & inBuffer[24] == 0x00)

//                    {

//                          memcpy(sbus_data,inBuffer,25);

//                          toChannels = 1;

//                          return;

//                    }

            }

     }

}

完整程序代码:


/*

  Multiple Serial test


  Receives from the main serial port, sends to the others.

  Receives from serial port 1, sends to the main serial (Serial 0).


  This example works only with boards with more than one serial like Arduino Mega, Due, Zero etc.


  The circuit:

  - any serial device attached to Serial port 1

  - Serial Monitor open on Serial port 0


  created 30 Dec 2008

  modified 20 May 2012

  by Tom Igoe & Jed Roach

  modified 27 Nov 2015

  by Arturo Guadalupi


  This example code is in the public domain.

*/


#define SBUS_SIGNAL_OK          0x00

#define SBUS_SIGNAL_LOST        0x01

#define SBUS_SIGNAL_FAILSAFE    0x03

#define ALL_CHANNELS



uint8_t sbus_data[25] = {

  0x00,0x00,0x00,0x20,0x00,0xff,0x07,0x40,0x00,0x02,0x10,0x80,0x2c,0x64,0x21,0x0b,0x59,0x08,0x40,0x00,0x02,0x10,0x80,0x00,0x00};

int16_t channels[18]  = {

  1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,0,0};

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    无线传输的特点,第1组字码非常容易受低电平干扰,往往会产生误码,所以程序可以丢弃处理。 对于跳码编码,同样可以用专用解码芯片(如HCS5XX )硬件解码,也可用内置KEELOQ解码软件的单片机进行软件解码。跳码......
    和红外发射电路组成。红外接收设备可由红外接收电路、红外解码芯片、电源和应用电路组成。通常为了使信号更好的被发射端发送出去,经常会将二进制数据信号调制成脉冲信号,通过红外发射管发射。常用......
    无需特定解码硬件,美科学家研发能破解各种代码的芯片;为了实现更高的处理效率,国外科学家研发一款“通用解码芯片”。麻省理工学院(MIT)近日宣布,携手波士顿大学(Boston University......
    第3 层音频编码标准, 使用MP3 标准对音频数据编码既可以获得较大的音乐数据压缩比,又可以得到较好的音乐回放质量。国内外现有的MP3 解码方案实现有2 种方案: 硬件和软件解码。利用专用解码芯片的硬件解码......
    扰其它电器设备。由于其无法穿透墙壁,故不同房间的家用电器可使用通用的遥控器而不会产生相互干扰;电路调试简单,只要按给定电路连接无误,一般不需任何调试即可投入工作;编解码容易,可进行多路遥控。由于各生产厂家生产了大量红外遥控专用......
    新型解码芯片创数据传输能效纪录,有望应用于虚拟现实和5G网络等领域; ORBGRAND能更快且更节能地对数据进行解码。图片来源:麻省理工学院 美国麻省理工学院领衔的科学家团队开发出一种解码器芯片......
    模块 音频解码模块包括2 大部分单片机控制器和专用MP3 音频解码芯片VS1003。 1. 2. 1 音频解码芯片VS1003 VS1003 是一个单片MP3/ WMA/ MIDI 音频解码......
    如何选择好的MP3芯片解码芯片是MP3的处理核心;生活中我们常见的,电子琴、考勤机、门铃提示器、语音玩具、游戏机、指纹锁等等,为了能够很好的还原声音一般都会在里面的主板装上MP3解码芯片。但是......
    基于WT588F02A-16S语音芯片在启蒙玩具用品中的应用解析;唯创知音的WT588F02A-16S语音芯片方案设计的玩具,具备播放语音内容的功能的同时可以扩展红外接收解码功能、触摸按键功能、电机......
    一个提供多功能集合一体的,蓝牙解码芯片,完美的集成了MP3、WMV 的硬解码芯片,支持蓝牙5.0协议,FM,录音,line输入等,存储器支持TF 卡驱动,flash,UU盘,支持......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>