飞控信号SBUS信号解析为PWM信号输出
1.修改STM32时钟频率:
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/!< SYSCLK, HCLK, PCLK2 and PCLK1 configuration —————————/
/!< Enable HSE /
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/!< Wait till HSE is ready and if Time out is reached exit /
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/!< Enable Prefetch Buffer /
FLASH->ACR |= FLASH_ACR_PRFTBE;
/*!< Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/*!< HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/*!< PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/*!< PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/*!< PLLCLK = 8MHz * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL3); **//RCC_CFGR_PLLMULL3设置倍频倍数:输出时钟频率=倍频数*晶振时钟**
/*!< Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/*!< Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/*!< Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/*!< Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /*!< If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
/*!< Go to infinite loop */
while (1)
{
}
}
}
2.串口时钟配置
打开串口时钟
void RCC_Configuration(void) // 启动USART1,2,3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //注意各串口所对应的时钟源不一样;
Uart1 用的是APB2
Uart2 用的是APB1
Uart3 用的是APB1
//奇偶检验
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
偶校验因为在每个字节后增加一位用于奇偶校验,因此每字节长度不是8位,而是9字节。
3.串口中断设置
#if 1
//初始化参数设置
USART_InitStructure.USART_BaudRate = 100000;//100000; //波特率100000
USART_InitStructure.USART_WordLength = USART_WordLength_9b; //字长8位
USART_InitStructure.USART_StopBits = USART_StopBits_2; //2位停止字节,USART_StopBits_2
USART_InitStructure.USART_Parity = USART_Parity_Even;//偶校验 //USART_Parity_No; //无奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打开Rx接收和Tx发送功能
USART_Init(USART3, &USART_InitStructure); //初始化
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //使能串口中断,这个必须加上
USART_Cmd(USART3, ENABLE); //启动串口
#endif
4.sbus协议:
S-BUS protocol
The protocol is 25 Byte long and is send every 14ms (analog mode) or 7ms (highspeed mode).
One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2), baudrate = 100’000 bit/s
The highest bit is send first. The logic is inverted (Level High = 1)
[startbyte] [data1] [data2] …. [data22] [flags][endbyte]
startbyte = 11110000b (0xF0)
data 1-22 = [ch1, 11bit][ch2, 11bit] …. [ch16, 11bit] (ch# = 0 bis 2047)
channel 1 uses 8 bits from data1 and 3 bits from data2
channel 2 uses last 5 bits from data2 and 6 bits from data3
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)
bit3 = n/a
bit2 = n/a
bit1 = n/a
bit0 = n/a
endbyte = 00000000b
3.接收程序实现:
在STM32中的具体实现,除了如上述内容配置串口参数,还需要写好中断函数,写好解析函数。思路很简单,利用间隔时间来区分两帧,收到一帧数据后,做如下检查:
字节数够不够?
第一个字节是不是0x0f?
最后一个字节是不是0x00?
检查flag中的标志位
举个中断接收函数例子:
void UART4_IRQHandler(void)
{
static uint8_t byteCNT = 0;
static uint32_t lastTime = 0;
uint32_t curTime;
uint32_t interval = 0;
HAL_NVIC_ClearPendingIRQ(UART4_IRQn);
//如果时间间隔大于3毫秒,则认为是新的一帧
if(lastTime == 0)
{
curTime = HAL_GetTick();
lastTime = curTime;
}
else
{
curTime = HAL_GetTick();
interval = curTime - lastTime;
lastTime = curTime;
if(interval >= 3)
{
if(byteCNT == 25 && uart4_cache1[0] == 0x0f && uart4_cache1[24] == 0x00)
{
rc_captured = 0;
memcpy(uart4_cache2, uart4_cache1, byteCNT);
rc_captured = 1;
}
byteCNT = 0;
}
}
if(RESET != __HAL_UART_GET_FLAG(&huart4, UART_FLAG_ORE))
{
__HAL_UART_CLEAR_FLAG(&huart4, UART_FLAG_ORE);
uart4_cache1[byteCNT++] = huart4.Instance->DR;
}
if(RESET != __HAL_UART_GET_FLAG(&huart4, UART_FLAG_RXNE))
{
uart4_cache1[byteCNT++] = huart4.Instance->DR;
}
}
4.sbus解析程序:
8楼
楼主| 发表于 2012-7-25 15:43 | 只看该作者
收到25包据后,通过下面的算法,可以对SBUS数据包进行解析
解析后数据如下
摇杆行程
中点 1024
+100 1696
+135 1931
-100 352
-135 117
回复
举报
huperzhu
9楼
楼主| 发表于 2012-7-25 15:44 | 只看该作者
算法
SBUS_SIGNAL_OK
0
SBUS_SIGNAL_LOST
1
SBUS_SIGNAL_FAILSAFE
2
unsigned int channels[20];
unsigned char sbus_data[30];
unsigned char failsafe_status,byte_in_sbus,bit_in_sbus,ch,bit_in_channel;
if(SBUS_IN_OK == 1)
{
SBUS_IN_OK = 0;
sbus_flag = sbus_convert(sbus_data);
if((sbus_flag == 0) && (failsafe_status==0))
{
update_PWM(channels);
}
}
unsigned char sbus_convert(unsigned char *data_in)
{
int i;
if ((data_in[0]==0x0F) && (data_in[24] == 0))
{
// clear channels[]
for (i=0; i<16; i++) {channels = 0;}
// reset counters
byte_in_sbus = 1;
bit_in_sbus = 0;
ch = 0;
bit_in_channel = 0;
// process actual sbus data
for (i=0; i<176; i++) {
if (data_in[byte_in_sbus] & (1<