stm32 解析sbus


轉載 https://blog.csdn.net/Brendon_Tan/article/details/89854751

STM32 Futaba SBUS協議解析
1. S.BUS
1.1 協議介紹

S.BUS是FUTABA提出的舵機控制總線,全稱Serial Bus,別名S-BUS或SBUS,也稱 Futaba S.BUS。
S.BUS是一個串行通信協議,也是一個數字串行通信接口(單線),適合與飛控連接。它可以連接很多設備,每個設備通過一個HUB與它相連,得到各自的控制信息。
S.BUS可以傳輸16個比例通道和2個數字(bool)通道。其硬件上基於RS232協議,采用TTL電平,但高位取反(負邏輯,低電平為“1”,高電平為“0”),通信波特率為100K(不兼容波特率115200)。

1.2 協議解析
通信接口:USART(TTL)
通信參數:1個起始位+8個數據位+偶校驗位+2個停止位,波特率=100000bit/s,電平邏輯反轉。
通信速率:每14ms(模擬模式)或7ms(高速模式)發送,即數據幀間隔為 11ms(模擬模式)或4ms(高速模式)。
數據幀格式:[1]
字節位 byte1 byte2-23 byte24 byte25
類型 開始字節 通道數據字節(含16個脈寬通道) 標志位字節(含2個數字通道) 結束字節
數據 0x0F 通道數據范圍11Bits = [0,2047] 2個數字通道位+2個狀態位 0x00
byte1:
startbyte = 0000 1111b (0x0F)

byte2-23:
databytes = 22bytes = 22 x 8Bits = 16 x 11Bits(CH1-16)
通道數據低位在前,高位在后,每個數據取11位,具體協議如下:
讀取的databyte值:

byte 2 3 4 5 6 7 etc
內容 12345678 12345678 12345678 12345678 12345678 12345678 etc
轉化后的通道值:

通道 CH01 CH02 CH03 CH04 etc
內容 67812345678 34567812345 81234567812 56781234567 etc
byte24:

Bit 7 6 5 4 3 2 1 0
含義 數字通道CH17 數字通道CH18 幀丟失位 故障保護激活位 N/A N/A N/A N/A
byte25:
endbyte = 0000 0000b (0x00)

2. 硬件設計
2.1 硬件參數
主控芯片:STM32F103VET6
接收端口:USART2(帶反相電路)
S.BUS設備:walkera RX-SBUS[2](配DEVO 10遙控器)
2.2 反相電路
由於此芯片串口不帶反相器,我們需要外部搭建反相電路。如果芯片串口內部帶反相器,可以省略此步。反相電路設計如下圖:


J1為4Pin排針,適配S.BUS接口,可5V輸出為SBUS接收機供電。
J1的Pin-4接S.BUS數據發送端,連接一個由NPN三極管構成的反相器,將反相后的信號送入芯片USART2的RXD引腳。
3.程序設計
3.1 數據接收
分析一:根據 1.2 的協議解析,開始字節(0x0F)和結束字節(0x00)都是數據字節中很容易出現的字節,所以不能完全作為數據幀接收開始和結束的標志。
分析二:每個數據幀之間的間隔至少4ms,則可以利用這個空閑時間來接收數據幀。(需要設計一個系統時鍾)
分析三:STM32 USART或UART有空閑中斷,即檢測到總線空閑(無數據傳輸),就產生中斷。
接收程序設計:綜上,利用USART2接收中斷(RXNE)來接收每個字節,利用USART2空閑中斷(IDLE)來判斷數據幀是否接收完畢。

USART2 初始化函數代碼如下:

/**
* @name SBUS_Configuration
* @brief Configure SBUS(Usart2) clock, gpio and nvic:
* SBUS_RX USART2_RX PD6
* @param None
* @retval None
*/
void SBUS_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);

// 波特率100000 8個數據位 偶校驗位 2個停止位
USART_InitStructure.USART_BaudRate = 100000;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //注意這里是9個數據長度(8個數據位+偶校驗位)
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx;

USART_Init(USART2, &USART_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);

USART_Cmd(USART2, ENABLE);
}

USART2 中斷函數代碼如下:


uint8_t USART2_RX_BUF[26];

/**
* @name USART2_IRQHandler
* @brief This function handles USART2 Handler
* @param None
* @retval None
*/
void USART2_IRQHandler(void)
{
uint8_t res;
uint8_t clear = 0;
static uint8_t Rx_Sta = 1;

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
res =USART2->DR;
USART2_RX_BUF[Rx_Sta++] = res;
}
else if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
{
clear = USART2->SR;
clear = USART2->DR;
USART2_RX_BUF[0] = Rx_Sta - 1;
Rx_Sta = 1;
}
}

USART2_RX_BUF為接收緩存區,定義為26個字節,第一個字節USART2_RX_BUF[0]為接收到的字節個數,后面為接收到的數據。
USART2_RX_BUF[0]可以作為數據幀字節長度的判斷。
中斷服務函數具體解釋請參考STM32 串口接收不定長字節數據。
3.2 數據處理
直接上代碼:

uint16_t CH[18]; // 通道值
uint8_t rc_flag = 0;

void Sbus_Data_Count(uint8_t *sBusData)
{

tempData[ 0 ] = ( (sBusData[ 2]&0x07) << 8 ) + sBusData[ 1]; //sBus[ 2] low3 + sBus[ 1] low8
tempData[ 1 ] = ( (sBusData[ 3]&0x3F) << 5 ) + (sBusData[ 2] >> 3 ); //sBus[ 3] low6 + sBus[ 2] high5
tempData[ 2 ] = ( (sBusData[ 5]&0x01) << 10) + (sBusData[ 4] << 2 ) + (sBusData[ 3] >> 6); //sBus[ 5] low1 + sBus[ 4] low8 + sBus[ 3] high2
tempData[ 3 ] = ( (sBusData[ 6]&0x0F) << 7 ) + (sBusData[ 5] >> 1 ); //sBus[ 6] low4 + sBus[ 5] high7
tempData[ 4 ] = ( (sBusData[ 7]&0x7F) << 4 ) + (sBusData[ 6] >> 4 ); //sBus[ 7] low7 + sBus[ 6] high4
tempData[ 5 ] = ( (sBusData[ 9]&0x03) << 9 ) + (sBusData[ 8] << 1 ) + (sBusData[ 7] >> 7); //sBus[ 9] low2 + sBus[ 8] low8 + sBus[ 7] high1
tempData[ 6 ] = ( (sBusData[10]&0x1F) << 6 ) + (sBusData[ 9] >> 2 ); //sBus[10] low5 + sBus[ 9] high6
tempData[ 7 ] = ( (sBusData[11]&0xFF) << 3 ) + (sBusData[10] >> 5 ); //sBus[11] low8 + sBus[10] high3

tempData[ 8 ] = ( (sBusData[13]&0x07) << 8 ) + sBusData[12]; //sBus[13] low3 + sBus[12] low8
tempData[ 9 ] = ( (sBusData[14]&0x3F) << 5 ) + (sBusData[13] >> 3 ); //sBus[14] low6 + sBus[13] high5
tempData[ 10 ] = ( (sBusData[16]&0x01) << 10) + (sBusData[15] << 2 ) + (sBusData[14] >> 6); //sBus[16] low1 + sBus[15] low8 + sBus[14] high2
tempData[ 11 ] = ( (sBusData[17]&0x0F) << 7 ) + (sBusData[16] >> 1 ); //sBus[17] low4 + sBus[16] high7
tempData[ 12 ] = ( (sBusData[18]&0x7F) << 4 ) + (sBusData[17] >> 4 ); //sBus[18] low7 + sBus[17] high4
tempData[ 13 ] = ( (sBusData[20]&0x03) << 9 ) + (sBusData[19] << 1 ) + (sBusData[18] >> 7); //sBus[20] low2 + sBus[19] low8 + sBus[18] high1
tempData[ 14 ] = ( (sBusData[21]&0x1F) << 6 ) + (sBusData[20] >> 2 ); //sBus[21] low5 + sBus[20] high6
tempData[ 15 ] = ( (sBusData[22]&0xFF) << 3 ) + (sBusData[21] >> 5 ); //sBus[22] low8 + sBus[21] high3


}
接收到的報文和解析出來的數據如下:
RX:0F E0 03 1F 58 C0 07 16 B0 80 05 2C 60 01 0B F8 C0 07 00 00 00 00 00 03 00
CH: 992 992 352 992 352 352 352 352 352 352 992 992 000 000 000 000
RX:0F 60 01 0B 58 C0 07 66 30 83 19 7C 60 06 1F F8 C0 07 00 00 00 00 00 03 00
CH: 352 352 352 992 1632 1632 1632 992 1632 992 992 992 000 000 000 000

接收的byte24數據並非和協議解析中的一樣,無論斷開遙控器還是連接遙控器,讀取的值都是0x03。
接收機只支持12個通道,所以通道13-16沒有值。
讀取的通道值中間值為992,最大值為1632,最小值為352。

sbus數據轉為 PWM數據

RcData = (uint16_t)(sbusData * 1.2504 + 1761.1) / 2;

4. 最后
提供兩個應用優化方向:

使用DMA+雙緩存器+串口空閑中斷讀取和解析數據,提升MCU的工作效率。
將讀取的通道值轉化成脈寬(0.5-2.5ms)輸出,用來控制模擬信號設備。
本協議解析就寫到這里。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM