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

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
固定翼飞控程序的编写需要涉及到许多方面,包括硬件控制、飞行控制、传感器读取、姿态控制等。以下是一个简单的固定翼飞控程序框架,供参考: ```c++ #include <Servo.h> #define THROTTLE_PIN 5 // 油门控制引脚 #define AILERON_PIN 6 // 副翼控制引脚 #define ELEVATOR_PIN 7 // 升降舵控制引脚 #define RUDDER_PIN 8 // 方向舵控制引脚 Servo throttle; // 油门舵机 Servo aileron; // 副翼舵机 Servo elevator; // 升降舵舵机 Servo rudder; // 方向舵舵机 void setup() { // 初始化引脚 throttle.attach(THROTTLE_PIN); aileron.attach(AILERON_PIN); elevator.attach(ELEVATOR_PIN); rudder.attach(RUDDER_PIN); } void loop() { // 读取传感器数据 float roll = read_roll(); // 读取横滚角 float pitch = read_pitch(); // 读取俯仰角 float yaw = read_yaw(); // 读取航向角 float altitude = read_alt(); // 读取高度 // 控制算法 float throttle_cmd = control_throttle(altitude); // 油门控制 float aileron_cmd = control_aileron(roll); // 副翼控制 float elevator_cmd = control_elevator(pitch); // 升降舵控制 float rudder_cmd = control_rudder(yaw); // 方向舵控制 // 输出控制信号 throttle.write(throttle_cmd); aileron.write(aileron_cmd); elevator.write(elevator_cmd); rudder.write(rudder_cmd); // 等待一段时间 delay(10); } float read_roll() { // 读取横滚角传感器数据 } float read_pitch() { // 读取俯仰角传感器数据 } float read_yaw() { // 读取航向角传感器数据 } float read_alt() { // 读取高度传感器数据 } float control_throttle(float altitude) { // 控制油门 } float control_aileron(float roll) { // 控制副翼 } float control_elevator(float pitch) { // 控制升降舵 } float control_rudder(float yaw) { // 控制方向舵 } ``` 需要注意的是,以上代码中的控制算法是简单的示例,实际应用中需要根据具体飞行控制要求进行修改和完善。此外,还需要添加其他的功能模块,例如遥控器解码、数据记录等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值