传统的遥控器接收机是采用多路PWM的方式进行输出的,遥控器中有多少个通道,接收机中就有多少路PWM输出,例如下图中的遥控器有6个可用通道,其接收机也有6个PWM输出通道与之对应:
此接收机除了PWM输出之外还有S.BUS协议输出方式,关于S.BUS我们已经在上一节中介绍过了,这里不再赘述。下面我们主要针对PWM信号输出来做讲解。
接收机的1-7个PWM输出通道,都是以PWM的形式输出的,这就需要飞控能够采集并解析这些PWM信号,并为飞控所用。我们知道PWM信号所表示的数值就是高电平持续时间占用整个周期时长的百分比,例如下图所示:
接收机输出的PWM与之前章节中讲述的电调需要接收的PWM完全一致。只不过我们需要使用飞控程序来读取接收机输出的PWM信号值。我们以第一个通道的PWM为例,讲述飞控程序对其处理的具体方法:
在STM32系列中,我们可以为GPIO引脚设置成PWM采集模式,并通过采集寄存器来读取当前PWM的周期和PWM占空比。
//定义PWM输入捕获引脚
#define GPIO_PWM_IN (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13)
void PWMIN::_timer_init(void)
{
//在定时器还没有使能之前关中断
irqstate_t flags = px4_enter_critical_section();
//配置PWM输入的GPIO引脚
px4_arch_configgpio (GPIO_PWM_IN);
px4_arch_configgpio (GPIO_VDD_RANGEFINDER_EN);
//配置中断向量
irq_attach(PWMIN_TIMER_VECTOR, pwmin_tim_isr, NULL);
//修改定时器寄存器
modifyreg32(PWMIN_TIMER_POWER_REG, 0, PWMIN_TIMER_POWER_BIT);
//配置定时器寄存器
rCR1 = 0;
rCR2 = 0;
rSMCR = 0;
rDIER = DIER_PWMIN_A;
rCCER = 0;
rCCMR1 = CCMR1_PWMIN;
rCCMR2 = CCMR2_PWMIN;
rSMCR = SMCR_PWMIN_1;
rSMCR = SMCR_PWMIN_2;
rCCER = CCER_PWMIN;
rDCR = 0;
//配置捕获周期
uint32_t prescaler = PWMIN_TIMER_CLOCK / 1000000UL;
rPSC = prescaler - 1;
//最大计数
rARR = UINT16_MAX;
rEGR = GTIM_EGR_UG;
//定时器使能
rCR1 = GTIM_CR1_CEN;
//开中断
up_enable_irq (PWMIN_TIMER_VECTOR);
px4_leave_critical_section(flags);
}
static int pwmin_tim_isr(int irq, void *context, void *arg)
{
uint16_t status = rSR;
uint32_t period = rCCR_PWMIN_A;
uint32_t pulse_width = rCCR_PWMIN_B;
//完成中断,清除标识位,允许继续中断
rSR = 0;
//处理得到的PWM数值
//
return OK;
}
每一个遥控器通道都需要一个PWM采集器进行采集,但是对于STM32来说不可能使用多个定时器来采集多个通道的PWM,这对于STM32的资源来说十分浪费。因此采用的就是PPM编码。PPM编码是PWM的扩展协议,可以在一个管脚中传输多路PWM信号。
PPM的频率通常是50Hz,周期长度20ms,每一个周期中可以存放最多10路PWM信号,每一路PWM的周期为2ms,如下图所示:
使用STM32的管脚中断配合定时器中的计数可以准确的捕获一个周期内的PPM信号中的高低电平变化,每2ms就是一路PWM信号的周期。
Copyright © 2015-2023 问渠网 辽ICP备15013245号