SBUS介绍

SBUS是Futaba公司定义的一种串口通信协议,Futaba的产品应用越来越广泛,不论是航模,无人机,还是机器人,遥控车,总能有它的身影。SBUS是一个接收机串行总线输出,通过这根总线,可以获得遥控器上所有通道的数据。目前很多模型及无人机电子设备都支持SBUS总线的接入。使用SBUS总线获取通道数据,效率高的,而且节省硬件资源,只需要一根线即可获取所有通道的数据。
官网网址:

https://os.mbed.com/users/Digixx/notebook/futaba-s-bus-controlled-by-mbed/

硬件介绍

和TTL串口信号相比,sbus的逻辑电平是反的,并且是硬件取反,软件取反是无效的;硬件取反的电路图如下:

esp 遥控器 接收器 遥控车接收器是什么_arm

协议介绍

串口配置为波特率100kbps,8位数据,偶校验(even),2位停止位,无流控。

链接https://mbed.org/users/Digixx/notebook/futaba-s-bus-controlled-by-mbed/说明了S-bus帧格式。每帧25个字节,按照如下顺序排列:

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

起始字节startbyte = 11110000b (0xF0),但实际上STM32(ARM核)收到的是0x0F。中间22个字节就是16个通道的数据了,为什么是16个通道?因为22x8=11x16,每个通道用11bit表示,范围是0-2047。波形图如下:

esp 遥控器 接收器 遥控车接收器是什么_嵌入式硬件_02


esp 遥控器 接收器 遥控车接收器是什么_stm32_03


esp 遥控器 接收器 遥控车接收器是什么_stm32_04

基本而言,data1为ch1的低8位,data2的低3位为ch1的高三位,data2的高5位是ch2的低5位,data3的低6位是ch2的高6位,以此类推,如下图所示:

esp 遥控器 接收器 遥控车接收器是什么_#define_05

代码介绍

sbus.c
            #include "sbus.h"
             ==说明:我所用的遥控器通过推动摇杆得到的最小值是193、中间值是993、最大值是1793==
			#define RC_CHANNEL_MIN      (-800)
			#define RC_CHANNEL_MAX      800
			#define SBUS_MIN_OFFSET     193
			#define SBUS_MID_OFFSET     993
			#define SBUS_MAX_OFFSET   1793
	/**
	 *@brief      这是一个C语言版的MAP函数(映射函数)
	 *@param  val:实际通道值; I_Min:输入最小值; I_Max:输入最大值;O_Min:输出最小值;O_Max:输出最大值
	 *@retval   实际输出值;
	 *@note    none
	 */
			int  output[16]={0};
			float map(float val, float I_Min, float I_Max, float O_Min, float O_Max)
			{
					return(((val-I_Min)*((O_Max-O_Min)/(I_Max-I_Min)))+O_Min);
			}
			/**
			  *@brief     协议转换
			  *@param  none
			  *@retval   none
			  *@note     none
	          */
			void  sbusPreparePacket(void)
			{
				uint16_t SBUS_channels[16]={0};
				if(Usart6_rx_buffer[0]==0x0f&& Usart6_rx_buffer[24]==0x00)    //校验收到的数据是否正确
			  {
			    SBUS_channels[0]  = (( Usart6_rx_buffer[1]| Usart6_rx_buffer[2]<<8)                     & 0x07FF);
			    SBUS_channels[1]  = (( Usart6_rx_buffer[2]>>3 | Usart6_rx_buffer[3]<<5)                 & 0x07FF);
			    SBUS_channels[2]  = (( Usart6_rx_buffer[3]>>6 | Usart6_rx_buffer[4]<<2 | Usart6_rx_buffer[5]<<10)  & 0x07FF);
			    SBUS_channels[3]  = (( Usart6_rx_buffer[5]>>1 | Usart6_rx_buffer[6]<<7)                 & 0x07FF);
			    SBUS_channels[4]  = (( Usart6_rx_buffer[6]>>4 | Usart6_rx_buffer[7]<<4)                 & 0x07FF);
			    SBUS_channels[5]  = (( Usart6_rx_buffer[7]>>7 | Usart6_rx_buffer[8]<<1 | Usart6_rx_buffer[9]<<9)   & 0x07FF) ;
			    SBUS_channels[6]  = (( Usart6_rx_buffer[9]>>2 | Usart6_rx_buffer[10]<<6)                & 0x07FF) ;
			    SBUS_channels[7]  = (( Usart6_rx_buffer[10]>>5| Usart6_rx_buffer[11]<<3)                & 0x07FF) ;
			    SBUS_channels[8]  = (( Usart6_rx_buffer[12]   | Usart6_rx_buffer[13]<<8)                & 0x07FF) ;
			    SBUS_channels[9]  = (( Usart6_rx_buffer[13]>>3| Usart6_rx_buffer[14]<<5)                & 0x07FF) ;
			    SBUS_channels[10] = (( Usart6_rx_buffer[14]>>6| Usart6_rx_buffer[15]<<2| Usart6_rx_buffer[16]<<10) & 0x07FF) ;
			    SBUS_channels[11] = (( Usart6_rx_buffer[16]>>1| Usart6_rx_buffer[17]<<7)                & 0x07FF) ;
			    SBUS_channels[12] = (( Usart6_rx_buffer[17]>>4| Usart6_rx_buffer[18]<<4)                & 0x07FF) ;
			    SBUS_channels[13] = (( Usart6_rx_buffer[18]>>7| Usart6_rx_buffer[19]<<1| Usart6_rx_buffer[20]<<9)  & 0x07FF) ;
			    SBUS_channels[14] = (( Usart6_rx_buffer[20]>>2| Usart6_rx_buffer[21]<<6)                & 0x07FF) ;
			    SBUS_channels[15] = (( Usart6_rx_buffer[21]>>5| Usart6_rx_buffer[22]<<3)                & 0x07FF) ;
			  }
			  else 
			  {
					SBUS_channels[2]=993;
				     SBUS_channels[3]=993;  
			   }
				for(char i=0;i<16;i++)
				{
					output[i]=map(SBUS_channels[i],SBUS_MIN_OFFSET,SBUS_MAX_OFFSET, RC_CHANNEL_MIN, RC_CHANNEL_MAX);   //具体到通道值
				}
			
			}
			
          /**
			  *@brief    输出PWM(混控)
			  *@param  offset_y:实际通道1的值;offset_x:实际通道2的值;c:给定常数
			  *@retval   none
			  *@note     none
	          */
			//应用到具体的通道  实现pwm输出
			//以通道3为y轴,通道4为x轴
			 int a,b, pwm1_channels[2]={0};
			void PWM_Out(int offset_y,int offset_x,float c )
			{	
			 
				sbusPreparePacket();
				if(offset_y>=0)
				{
					a=(c*offset_y*offset_y+800*offset_x)/(800+c*offset_y);  //电机1
			   	    b=(c*offset_y*offset_y-800*offset_x)/(800+c*offset_y);  //电机2
					pwm1_channels[0]=map(a,0,800,1500,2000);
					pwm1_channels[1]=map(b,0,800,1500,2000);
				}
			
				if(offset_y<0)
				{
					a=(1-2*0.25)*offset_y-0.25*(100+offset_x);
					b=(1-2*0.25)*offset_y-0.25*(100-offset_x);
					pwm1_channels[0]=map(a,-800,0,1000,1500);
					pwm1_channels[1]=map(b,-800,0,1000,1500);
				}
				
				pwm_out1(	pwm1_channels[0]);
				pwm_out2(	pwm1_channels[1]);
			} 
sbus.h
            #ifndef __SBUS_H
			#define __SBUS_H
			#include "main.h"
			#include "usart.h"
			#include "tim.h"
			#include <stdbool.h>
			extern int  output[16];
			#define pwm_out1(pwm)     __HAL_TIM_SET_COMPARE(&htim15,TIM_CHANNEL_1,pwm)
			#define pwm_out2(pwm)     __HAL_TIM_SET_COMPARE(&htim15,TIM_CHANNEL_2,pwm) 
			uint16_t PWM_OUT1(uint16_t pwm_channel);
			uint16_t PWM_OUT2(uint16_t pwm_channel);
			float map(float val, float I_Min, float I_Max, float O_Min, float O_Max);
			void  sbusPreparePacket(void);
			void GET_SBUSDATA(void);
			void sbus_control(void);
			void   PWM_Out(int offset_y,int offset_x,float c );
			#endif

完结