飞控信号SBUS信号解析为PWM信号输出

飞控信号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中的具体实现,除了如上述内容配置串口参数,还需要写好中断函数,写好解析函数。思路很简单,利用间隔时间来区分两帧,收到一帧数据后,做如下检查:

  1. 字节数够不够?

  2. 第一个字节是不是0x0f?

  3. 最后一个字节是不是0x00?

  4. 检查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 | 只看该作者
算法

define

SBUS_SIGNAL_OK

0

define

SBUS_SIGNAL_LOST
1

define

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<

你可能感兴趣的:(STM32)