飞控信号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<


喝水不忘挖井人:http://blog.csdn.net/mish84/article/details/51512718


PPM信号,是遥控控制和接收以及电调油门控制舵机控制的最最重要的信号,当然玩模拟器在电脑软件里练飞行时也离不开PPM信号。如果只是单纯玩也没有必要了解那么仔细,但作为的专业的知识帖知识点是有必要弄清楚的,甚至在开发航模遥控时,给微控制器编程都是要深入了解的。


纵览许多论坛,都没有谁能说得清楚的完整的,这里我也就抛砖引玉了。不管看帖的懂不懂,我也直入主题了:


PPM信号格式:


1、老标准:1~2毫秒是单个通道的总脉宽,其中低电平是固定的占0.3毫秒,高电平从0.7~1.7毫秒可变,脉宽越大油门越高。


2、新的标准:每个通道1~2毫秒脉宽,周期20毫秒,即高电平5V宽度为1毫秒代表低速(油门通道,舵机通道舵杆是打到一头的顶),那剩下的19毫秒是低电平0V;1.5毫秒低表舵机通道舵杆是打到中心位置,那剩下的18.5毫秒是低电平0V;2毫秒代表高速(油门通道,舵机通道舵杆是打到另一头的顶),那剩下的18毫秒是低电平0V,如图。这样,发射端每20毫秒发射一次,总共可以容纳10个比例通道。在接收端,把每个通道分离出来,脉宽信号也是20毫秒更新一次。


3、对于双向电调,是以1.5毫秒脉冲宽度为停止点,1毫秒脉宽时反转最高速,2毫秒脉宽时正转最高速。


在接收端分离出各个通道的信号输出给被控对象:如电调,舵机等,是不是可以理解为,是PWM(脉宽调制)信号呢?可以这么说,不能简单地把接收输出的控制信号,理解为PWM信号,接收输出的单通信号可周期可以是18~22毫秒,或者16~25毫秒都可以认为是正常的,要求严格的是那个高电平的1~2毫秒的脉冲信号。


无线遥控就是利用高频无线电波实现对模型的控制。Futuba具有自动跳频抗干扰能力,从理论上讲可以让上百人在同一场地同时遥控自己的模型而不会相互干扰。而且在遥控距离方面也颇具优势,2.4 GHz遥控系统的功率仅仅在100 mW以下,而它的遥控距离可以达到1km以上。

每个通道信号脉宽0~2ms,变化范围为1~2ms之间。1帧PPM信号长度为20ms,理论上最多可以有10个通道,但是同步脉冲也需要时间,模型遥控器最多9个通道。
PPM格式

你可能感兴趣的:(STM32)