STM32输入捕获

您所在的位置:网站首页 STM32pwm波占空比测速 STM32输入捕获

STM32输入捕获

2023-11-08 16:33| 来源: 网络整理| 查看: 265

前言 博文基于STM32F103ZET6和标准固件库V3.5.0在MDK5环境下开发;本博文只讨论输入捕获的PWM输入模式,这个模式是STM32输入捕获检测脉宽和频率的一种硬件处理机制,说白了就是STM32芯片专门用来进行对PWM进行捕获的一个功能;此方法相比较于传统的PWM的捕获方法,大大减小了代码量,提高了检测效率,而实际上对于PWM信号的检测还有其他方法(下面我会介绍,就是原子教程提供的方法),并且关于繁琐的寄存器的介绍这里就不多说了,有兴趣的话可以直接去我的另外一个博客里去看: https://blog.csdn.net/wuyuzun/article/details/73135662 ;(备注:此链接里的博客里有一个配套的例程,例程的思想来自于源子教程,然而本博客是向突出介绍“PWM输入模式”这种我认为更好的方法)本片博文只介绍单路(一个定时器)的PWM输入模式的,如果想实现多路PWM同时检测,只需要对其他具有输入捕获功能的定时器相同配置即可(我会在另外一个博客里进行介绍);如有不足之处,多指教; 什么是PWM输入模式以及相应配置流程

在这里插入图片描述 (截图来自《STM32中文参考手册_V10》第216页) 介绍:(我们通过比较原子提供的思路来分析一下“PWM输入模式的比较模式”) 原子的思路: 在这里插入图片描述 如图为某个引脚输入的PWM波,把它分为4~5的阶段进行编程: ① 此时设置好上升沿为触发中断,以及其他定时器配置; ② 此时产生了上升沿,进行捕获操作,CNT内的值捕获到CCR内,此时使CNT=0,CNT继续开始计数;当完成捕获,并且修改捕捉极性为下降沿捕获,当下降沿来到时,将会再次触发此中断函数; ③ 此时产生了下降沿,触发了中断函数; ④ 清0 TIMx_SR寄存器中CCxOF和CCxIF位。

PWM输入模式: 在这里插入图片描述 (图片中为定时器输入捕获模式涉及到的功能模块,来自《STM32中文使用手册》P200页) 如图,举一个输入引脚为例(但是只能举TIMx_CH1和TIMx_CH2,因为TIMx_CH3和TIMx_CH4没有今天所要讨论的PWM输入模式这个功能,),假设这里对TIMx_CH1输入的信号同原子思路中的一样;那么我们同样可以用上面那种图来分析①~⑤五个步骤: ①:配置相对应的输入捕获引脚TIMx_CH1和GPIO管脚的映射关系; ②:选择TIMx_CCR1为有效输入:置TIMx_CCMR1寄存器的CC1S=01(这步的配置决定了此时的CCR1寄存器是输入用的还是输出用的,因为每个可以执行捕获和比较功能的定时器同一时间,只能执行捕获或者输出,两者不能同时进行);在这里插入图片描述 ③:选择TI1FP1的有效极性(用来捕获数据到TIMx_CCR1和清除计数器CNT),置CC1P=0(上升沿有效) 在这里插入图片描述 ④:选择TIMx_CCR2的有效输入:置TIMx_CCMR1寄存器的CC2S=10(选中TI1)。(这里是需要特别注意的一个地方,从下图的配置选择或者从上面电路方框图的绿色剪头可以看出来,其实IC1和IC2配置时选择的输入信号都是来自于CH1通道进来的信号)在这里插入图片描述 ⑤:选择TI1FP2的有效极性(捕获CNT的数据到TIMx_CCR2);置CC2P=1(下降沿有效)。(图片参考了CC1P的配置,这里可以注意到一个现象就是IC2选择下降沿触发捕获,而IC1选择的是信号上升沿触发捕获) 在这里插入图片描述 ⑥:选择有效的触发输入信号:置TIMx_SMCR寄存器中的TS = 101(选择TI1FP1); 在这里插入图片描述 ⑦:配置从模式寄存器为复位模式:置TIMx_SMCR中的SMS=100;(这一步决定每次上升沿出现,CNT就被清零)在这里插入图片描述 ⑧:使能捕获:配置TIMx_CCER寄存器中CC1E=1且CC2E=1;

从波形的角度分析工作原理 在这里插入图片描述 ①:在一处完成上述配置(当然,上述的配置只是简单地寄存器配置,并没写中断函数等等,这个工作,可以放在后续): ②:一条路上的CH1,TI1,TI1FP1,TI1FP2的上升沿同时产生,CNT内的值被捕获到了CCR1内并且CNT被清零,从新开始计数; ③:一条路上的CH1,TI1,TI1FP1,TI1FP2的下降沿同时产生,CNT内的值被捕获到了CCR2内,不清零CNT; ④~⑤:在编写的中断函数内即可进行逻辑操作,获取此时CCR1(周期)和CCR2(高电平时间),即可计算占空比 = CCR2/CCR1; 下面即使相对应的代码:

/*---------------PWM输入对应管脚配置-----------------*/ static void PWM_Intput_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // TIM1 对应 PA8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入模式; GPIO_Init(GPIOA, &GPIO_InitStructure); } /*-------------中断嵌套配置------------*/ static void PWM_Intput_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /*-------------TIM1模式配置------------*/ static void PWM_Intput_Mode_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); /*--------------------时基结构初始化-------------------------*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period=0xffff; //ARR=65535us TIM_TimeBaseStructure.TIM_Prescaler= 72-1; //PSC = 1M = 1us; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //分频因子为0,即不分频; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //CNT为向上计数模式; TIM_TimeBaseStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /*-------------------输入捕获结构体初始化------------------*/ TIM_ICInitTypeDef TIM_ICInitStructure; //配置CH1 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿触发 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1直接连接TI1FP1 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //对输入的PWM信号不分频 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_PWMIConfig(TIM1, &TIM_ICInitStructure); //配置CH2 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿触发; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI; //IC2间接连接TI1FP2 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //对输入的PWM信号不分频 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_PWMIConfig(TIM1, &TIM_ICInitStructure); //选择输入捕获的触发信号; TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1); // 选择从模式 // PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT被复位清零; TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable); // 使能捕获中断,这个中断主要针对的是主捕获通道(TI1FP1) TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); // 清除中断标志位 TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); // 计数器开始计数 TIM_Cmd(TIM1, ENABLE); } /*---------------PWM输入对应管脚配置-----------------*/ static void PWM_Intput_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // TIM1 对应 PA8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入模式; GPIO_Init(GPIOA, &GPIO_InitStructure); } /*-------------中断嵌套配置------------*/ static void PWM_Intput_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void TIM1_CC_IRQHandler(void) { uint8_t IC1_CCR1,IC2_CCR2; TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); IC1_CCR1 = TIM_GetCapture1(TIM1); //获取周期值CCR1 IC2_CCR2 = TIM_GetCapture2(TIM1); //获取高电平时间CCR2 /*逻辑代码*/ } /*-------------TIM1模式配置------------*/ static void PWM_Intput_Mode_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); /*--------------------时基结构初始化-------------------------*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period=0xffff; //ARR=65535us TIM_TimeBaseStructure.TIM_Prescaler= 72-1; //PSC = 1M = 1us; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //分频因子为0,即不分频; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //CNT为向上计数模式; TIM_TimeBaseStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /*-------------------输入捕获结构体初始化------------------*/ TIM_ICInitTypeDef TIM_ICInitStructure; //配置CH1 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿触发 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1直接连接TI1FP1 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //对输入的PWM信号不分频 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_PWMIConfig(TIM1, &TIM_ICInitStructure); //配置CH2 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿触发; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI; //IC2间接连接TI1FP2 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //对输入的PWM信号不分频 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_PWMIConfig(TIM1, &TIM_ICInitStructure); //选择输入捕获的触发信号; TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1); // 选择从模式 // PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT被复位清零; TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable); // 使能捕获中断,这个中断主要针对的是主捕获通道(TI1FP1) TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); // 清除中断标志位 TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); // 计数器开始计数 TIM_Cmd(TIM1, ENABLE); }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3