STM32与Futaba遥控器进行S.Bus的通讯程序

Futaba(日本双叶电子工业,戏称“扶他爸”)的遥控器用航模中使用较为广泛的遥控器。S.Bus则是Futaba公司提出的舵机控制总线。本篇博文主要以T6K为对象,介绍STM32与S.Bus协议的遥控器进行通讯的实例。

STM32与Futaba遥控器进行S.Bus的通讯程序_第1张图片

图1 Futaba T6K-V2

1、硬件电路

硬件上,它基于RS232协议,但高位取反(低电平表示1;高电平表示0),即信号反相。SBUS采用负逻辑,所以无论接收还是发送都要进行硬件取反(注意,一定要硬件取反),下图是带隔离的S.Bus接收信号电路:
STM32与Futaba遥控器进行S.Bus的通讯程序_第2张图片

图 2 信号取反隔离电路

2、遥控接收机设置

Futaba T6K-V2配备的信号接收机为R3006SB。主控制器与遥控接收机的6通道进行连接,见下图,注意:黄红黑分别为信号、电源正极、电源负极。
STM32与Futaba遥控器进行S.Bus的通讯程序_第3张图片

图 3 遥控接收机与主控板的链接

Futaba R3006SB有Mode A和Mode B两种输出模式。其区别见图 4,在Mode A模式下,通道6输出PWM信号;在Mode B下通道6输出S.Bus信号。
STM32与Futaba遥控器进行S.Bus的通讯程序_第4张图片

图 4 R3006SB的输出模式

Futaba R3006SB有Mode A和Mode B两种输出模式的相互切换非常简单。操作步骤如下:

  1. 在遥控关闭的状态下,给接收机供电,接收机上电后接收机的红灯会闪3下,然后变成固定的红灯常亮;
  2. 用工具长按SW按键超过5秒,直到LED灯红、绿快速交替闪烁时松开,此时接收机进入通道设置模式;

STM32与Futaba遥控器进行S.Bus的通讯程序_第5张图片

图 5 R3006SB模式切换按钮
  1. 此时LED红灯闪烁的规律即为当前所设置的模式:Mode A下每间隔一段时间红灯闪一次;Mode B下每间隔一段时间红灯闪两次。
  2. 如果需要切换通道输出模式,则用工具按一下SW按钮即切换Mode A或Mode B;
  3. 最后,再用工具戳SW按键超过2秒,直到LED灯红、绿快速交替闪烁时松开,此时通道模式即已配置完成;
  4. 重新给接收机上电即可。

3、通讯程序

S.Bus支持16个比例+2个布尔共18个通道 。S-BUS的协议由25个字节构成,更新率为14ms(模拟)或7ms(高速模式),波特率100kbps。

3.1 初始化

在这里,使用STM32的USART2作为与遥控器接收机通讯的串口端口,按RS232正常配置即可,另外,需要注意SBUS要求波特率为100k。

void sbus_init(u32 bound)//SBUS波特率要求100K 
{
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	//USART2_TX   PA.2
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);
	//USART2_RX	  PA.3
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA.3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
	//NVIC配置
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =5;		//子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//设置波特率;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_2;//2个停止位
	USART_InitStructure.USART_Parity = USART_Parity_Even;//偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART2, &USART_InitStructure); //初始化串口
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
  USART_Cmd(USART2, ENABLE);                    //使能串口 
}

3.2 信号接收程序

在这里采用中断接收方式:

void USART2_IRQHandler(void) //串口2中断服务程序
{
   u8 i;	
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
	{
	  sBUF[RC_LEN++]=USART_ReceiveData(USART2);
		//if(sBUF[0]==0x0f&&sBUF[24]==0x08&&RC_LEN==25)//如果帧头和帧尾满足		
		if(sBUF[0]==0x0f&&RC_LEN==25)//如果帧头和帧尾满足
		{
		  RC_LEN=0;
		  for(i=0;i<25;i++)
			{
				if(i==0) uart2RxFlag=0;
			  Data[i]=0;
			}//清零数组
			for(i=0;i<25;i++)
			{
			  Data[i]=sBUF[i];
			}
			uart2RxFlag=1;
		}
	} 
}

3.3 数据解析

S.BUS每个字节11位,定义如下:
O n e B y t e = 1 s t a r t b i t + 8 d a t a b i t + 1 p a r i t y b i t + 2 s t o p b i t ( 8 E 2 ) One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2) OneByte=1startbit+8databit+1paritybit+2stopbit(8E2)

而每个包25字节如下:
[startbyte] [data1] [data2] … [data22] [flags][endbyte]
其中,startbyte = 11110000b (0xF0);
data 1-22 放入16个通道 [ch1, 11bit][ch2, 11bit] … [ch16, 11bit] ,每个通道取值范围:(ch# = 0 bis 2047)。拼接如下:
channel 1 uses 8 bits from data1 and 3 bits from data2(共11 bits)
channel 2 uses last 5 bits from data2 and 6 bits from data3(共11 bits)
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)
结束字节endbyte = 00000000b
解析的代码如下:

void Cal_RcData(void)//解析收到的通道数据
{
    u8 i,j=0;
    for(i=1;i<23;i++)
    {
      data_22[j++]=Data[i];//摘取22位通道数据
    }
    for(i=0;i<22;i++)//转换位2进制存储
    {
      int k=1;
      for(j=0;j<8;j++)
      {
         data_b[j+8*i]=(data_22[i]&k)>>j;
         k<<=1;
      }
    }
    for(i=0;i<16;i++)//清零过程,不清零莫名奇妙的错误
     {
          data_ch[i]=0x00;
     }
    for(j=0;j<16;j++)//转换为SBUS要求的格式
     {
         for(i=10;i>0;i--)
          {
             data_ch[j]=data_ch[j]|(data_b[i+j*11]<<i);
          }
     }
}

你可能感兴趣的:(STM32杂耍)