本文主要是介绍STM32定时器输入捕获航模接收机信号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
STM32定时器输入捕获航模接收机信号
- 前言
- 一、舵机信号(PWM)
- 二、STM32输入捕获功能框图
- 三、输入捕获初始化结构体定义及说明
- 三、代码
前言
最近在做一个检测航模接收机输出的舵机信号,并根据信号不同执行相应功能的小项目。硬件部分使用的是STM32F103C8T6通用定时器TIM3的通道1和通道2分别做两路信号的输入捕获(Input Capture)。
提示:以下是本篇文章正文内容,下面案例可供参考,如有错误,欢迎批评指正!
一、舵机信号(PWM)
PWM就是脉冲宽度调制,也就是占空比可调的脉冲信号。航模接收机输出的舵机PWM信号一般是频率为50HZ即周期为20ms,信号的高电平时间在1000us-2000us之间变化的PWM波,并且当遥控器打到中位时,信号高电平时间为1500us,如下图所:
二、STM32输入捕获功能框图
STM32F103通用定时器输入捕获功能框图如下所示,主要包括捕获通道选择、滤波器设置、捕获极性设置、映射关系设置及分频器配置等部分。
三、输入捕获初始化结构体定义及说明
STM32标准库的stm32f10x_tim.h中定义了定时器输入捕获初始化结构体:
/** * @brief TIM Input Capture Init structure definition */typedef struct
{uint16_t TIM_Channel; /*!< 输入通道选择,共4个通道。TIM_Channel_1->TIM_Channel_4 */uint16_t TIM_ICPolarity; /*!< 输入捕获极性设置,可选择上升沿捕获或下降沿捕获或两者都可捕获。TIM_ICPolarity_Rising/TIM_ICPolarity_Falling/TIM_ICPolarity_BothEdge */uint16_t TIM_ICSelection; /*!< 输入捕获通道选择,共3个通道。TIM_ICSelection_DirectTI/TIM_ICSelection_IndirectTI/TIM_ICSelection_TRC */uint16_t TIM_ICPrescaler; /*!< 输入捕获通道预分频。可设置分频因子为1、2、4、8*/uint16_t TIM_ICFilter; /*!< 输入捕获滤波器设置。可设置为0x00到0x0F,一般不用设置为0x00 */
} TIM_ICInitTypeDef;
三、代码
#include "drv_pwm.h"u8 TIM3_CHL1_CaptureFlag; // TIM3 CH1捕获标志
u32 TIM3_CHL1_Rising_Value ; // TIM3 CH1捕获上升沿值
u32 TIM3_CHL1_Falling_Value ; // TIM3 CH1捕获下降沿值
u16 TIM3_CHL1_PWM1_pulse; // TIM3 CH1捕获PWM脉宽数值u8 TIM3_CHL2_CaptureFlag; // TIM3 CH2捕获标志
u32 TIM3_CHL2_Rising_Value ; // TIM3 CH2捕获上升沿值
u32 TIM3_CHL2_Falling_Value ; // TIM3 CH2捕获下降沿值
u16 TIM3_CHL2_PWM1_pulse; // TIM3 CH2捕获PWM脉宽数值void drv_pwm_init(void)
{GPIO_InitTypeDef GPIO_InitStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_ICInitTypeDef TIM_ICInitStruct;NVIC_InitTypeDef NVIC_InitStruct;/* 打开GPIO时钟 */RCC_APB2PeriphClockCmd(TIMX_PORT_CLK, ENABLE);/* 打开定时器时钟 */RCC_APB1PeriphClockCmd(TIMX_CLK, ENABLE); /* 初始化PA6/PA7为下拉输入 */GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStruct.GPIO_Pin = PWM_TIMX_CHL1_PIN | PWM_TIMX_CHL2_PIN ;GPIO_Init(TIMX_PORT, &GPIO_InitStruct);GPIO_ResetBits(TIMX_PORT,PWM_TIMX_CHL1_PIN);GPIO_ResetBits(TIMX_PORT,PWM_TIMX_CHL2_PIN);/* 初始化定时器1配置 */TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数TIM_TimeBaseInitStruct.TIM_Period = 65535 - 1;TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1; // 1usTIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIMX, &TIM_TimeBaseInitStruct);/* 初始化定时器3中断 */NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = TIMX_INTERRUPT;NVIC_Init(& NVIC_InitStruct);/* 初始化定时器3捕获通道1配置 */TIM_ICInitStruct.TIM_Channel = PWM_TIMX_CHL1 ;TIM_ICInitStruct.TIM_ICFilter = 0x00;TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling; // 下降沿开始捕获(由于原理图中光耦对PWM做了反向,所以下降沿开始捕获)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIMX, &TIM_ICInitStruct);/* 初始化定时器3捕获通道1配置 */TIM_ICInitStruct.TIM_Channel = PWM_TIMX_CHL2 ;TIM_ICInitStruct.TIM_ICFilter = 0x00;TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling; // 下降沿开始捕获(由于原理图中光耦对PWM做了反向,所以下降沿开始捕获)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIMX, &TIM_ICInitStruct);/* 使能 */TIM_ITConfig(TIMX,TIM_IT_CC1,ENABLE);TIM_ITConfig(TIMX,TIM_IT_CC2,ENABLE);/* 使能定时器 */TIM_Cmd(TIMX, ENABLE);
}void TIM3_IRQHandler(void)
{OS_CPU_SR cpu_sr = (OS_CPU_SR)0;OS_ENTER_CRITICAL();OSIntEnter();OS_EXIT_CRITICAL();if(TIM_GetITStatus(TIMX, TIM_IT_CC1) == SET){TIM_ClearITPendingBit(TIMX, TIM_IT_CC1); // 清除标志位if (TIM3_CHL1_CaptureFlag == 1){TIM3_CHL1_Rising_Value = TIM_GetCapture1(TIMX); // 获取当时检测到上升沿时候CCR寄存器的计数值if (TIM3_CHL1_Rising_Value < TIM3_CHL1_Falling_Value) // 说明当时获取CCR的值大于65535Temp1_Value = 65535;elseTemp1_Value = 0;TIM3_CHL1_PWM1_pulse = TIM3_CHL1_Rising_Value - TIM3_CHL1_Falling_Value + Temp1_Value; // 计算出PWM1脉宽值 TIM3_CHL1_CaptureFlag = 0;TIM_OC1PolarityConfig(TIMX, TIM_ICPolarity_Falling); // 设置下降沿捕获}else if (TIM3_CHL1_CaptureFlag == 0){TIM3_CHL1_Falling_Value = TIM_GetCapture1(TIMX); // 获取当时检测到下降沿时候CCR寄存器的计数值TIM3_CHL1_CaptureFlag = 1;TIM_OC1PolarityConfig(TIMX, TIM_ICPolarity_Rising); // 设置上升沿捕获}}if(TIM_GetITStatus(TIMX, TIM_IT_CC2) == SET){TIM_ClearITPendingBit(TIMX, TIM_IT_CC2); // 清除标志位if (TIM3_CHL2_CaptureFlag == 1){TIM3_CHL2_Rising_Value = TIM_GetCapture2(TIMX); // 获取当时检测到上升沿时候CCR寄存器的计数值if (TIM3_CHL2_Rising_Value < TIM3_CHL2_Falling_Value) // 说明当时获取CCR的值大于65535Temp2_Value = 65535;elseTemp2_Value = 0;TIM3_CHL2_PWM1_pulse = TIM3_CHL2_Rising_Value - TIM3_CHL2_Falling_Value + Temp2_Value; // 计算出PWM2的脉宽值TIM3_CHL2_CaptureFlag = 0;TIM_OC2PolarityConfig(TIMX, TIM_ICPolarity_Falling); // 设置下降沿捕获}else if (TIM3_CHL2_CaptureFlag == 0){TIM3_CHL2_Falling_Value = TIM_GetCapture2(TIMX); // 获取当时检测到下降沿时候CCR寄存器的计数值TIM3_CHL2_CaptureFlag = 1;TIM_OC2PolarityConfig(TIMX, TIM_ICPolarity_Rising); // 设置上升沿捕获}}OSIntExit();
}
TIM3_CHL1_PWM1_pulse 及TIM3_CHL2_PWM1_pulse 即为获取的两路PWM高电平的时间,单位为us。
提示:以上是本篇文章全部内容,如有错误,欢迎批评指正!
----2023年5月7日 南京 多云 微凉
这篇关于STM32定时器输入捕获航模接收机信号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!