STM32與Futaba遙控器進行S.Bus的通訊程序

Futaba(日本雙葉電子工業,戲稱“扶他爸”)的遙控器用航模中使用較爲廣泛的遙控器。S.Bus則是Futaba公司提出的舵機控制總線。本篇博文主要以T6K爲對象,介紹STM32與S.Bus協議的遙控器進行通訊的實例。

在這裏插入圖片描述

圖1 Futaba T6K-V2

1、硬件電路

硬件上,它基於RS232協議,但高位取反(低電平表示1;高電平表示0),即信號反相。SBUS採用負邏輯,所以無論接收還是發送都要進行硬件取反(注意,一定要硬件取反),下圖是帶隔離的S.Bus接收信號電路:
在這裏插入圖片描述

圖 2 信號取反隔離電路

2、遙控接收機設置

Futaba T6K-V2配備的信號接收機爲R3006SB。主控制器與遙控接收機的6通道進行連接,見下圖,注意:黃紅黑分別爲信號、電源正極、電源負極。
在這裏插入圖片描述

圖 3 遙控接收機與主控板的鏈接

Futaba R3006SB有Mode A和Mode B兩種輸出模式。其區別見圖 4,在Mode A模式下,通道6輸出PWM信號;在Mode B下通道6輸出S.Bus信號。
在這裏插入圖片描述

圖 4 R3006SB的輸出模式

Futaba R3006SB有Mode A和Mode B兩種輸出模式的相互切換非常簡單。操作步驟如下:

  1. 在遙控關閉的狀態下,給接收機供電,接收機上電後接收機的紅燈會閃3下,然後變成固定的紅燈常亮;
  2. 用工具長按SW按鍵超過5秒,直到LED燈紅、綠快速交替閃爍時鬆開,此時接收機進入通道設置模式;

在這裏插入圖片描述

圖 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位,定義如下:
OneByte=1startbit+8databit+1paritybit+2stopbit(8E2)One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (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);
          }
     }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章