每日速递:详解STM32定时器捕获功能
一、STM32定时器捕获功能
(相关资料图)
STM32的定时器是支持信号输入捕获的,何为输入捕获?主要做什么应用?
输入捕获:通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变的时候,将当前的定时器的值(TIMx_CNT)存放到对应的捕获比较寄存器里面,完成一次捕获。输入捕获主要应用于测量信号的脉宽或频率。
下图是定时器原理图的输入捕获框图部分
第一部分是设置滤波器,用来对信号进行滤波,信号从TI1输入,通过滤波器,输出TIF信号,正常情况下信号没有抖动,TI1F信号等于TI1的输入信号。
ICF[3:0]用来设置输入采样频率的数字滤波器的长度,如ICF=0011,会在捕获上升沿时,以fCK_INT的频率连续采样八次通道1的信号电平,若都为高电平,则说明这是一个有效的触发,就会触发捕获中断,这样就可以滤除那些高电平低于八个采样周期的脉冲信号,达到滤波的效果,如果不做滤波处理,设置为ICF=0000,只要检测到跳边沿,就会触发捕获。
在TIMx捕获/比较模式寄存器(TIMx_CCMR1)的位7:4
fDTS频率根据TIMx_CR1的CKD[1:0]设置
位9:8 CKD:时钟分频,此位域指示定时器时钟(CK_INT)频率与数字滤波器所使用的采样时钟(ETR、TIx)之间的分频比。
第二部分:设置输入捕获极性:配置边沿检测器检测上升沿还是下降沿。在TIMx捕获/比较使能寄存器(TIMx_CCER)的
第三部分:设置输入捕获映射通道:通道一信号也可以映射到通道二上,同理通道二信号也可以映射到通道一上。在TIMx捕获/比较模式寄存器(TIMx_CCMR1)的
第四部分:设置输入输出捕获分频器,就是设置检测到几次跳变后触发捕获。在TIMx捕获/比较模式寄存器(TIMx_CCMR1)的
同时要开启输入捕获1使能,在TIMx捕获/比较使能寄存器(TIMx_CCER)的
第五部分:捕获到有效信号开启中断。在DMA/中断使能寄存器(TIMx_DIER)
二、输入捕获配置步骤
输入捕获配置的一般步骤
① 初始化定时器和通道对应IO的时钟。
② 初始化IO口,模式为复用:
③设置引脚复用映射:
④初始化定时器ARR,PSC
⑤初始化输入捕获通道
⑥如果要开启捕获中断,
⑦使能定时器:
⑧编写中断服务函数:
三、输入捕获编程
以TIM5_CH1为例,
//定时器5通道1输入捕获配置//arr:自动重装值(TIM5是32位)//psc:时钟预分频数void TIM5_CH1_Cap_Init(u32 arr,u16 psc){ RCC->APB1ENR|=1<<3; //TIM5 时钟使能 RCC->AHB1ENR|=1<<0; //使能PORTA时钟 GPIO_Set(GPIOA,PIN0,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);//复用功能,下拉 GPIO_AF_Set(GPIOA,0,2); //PA0,AF2 TIM5->ARR=arr; //设定计数器自动重装值 TIM5->PSC=psc; //预分频器 TIM5->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上 TIM5->CCMR1|=0<<4; //IC1F=0000 配置输入滤波器 不滤波 TIM5->CCMR1|=0<<10; //IC1PS=00 配置输入分频,不分频 TIM5->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上 TIM5->CCER|=0<<1; //CC1P=0 上升沿捕获 TIM5->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中 TIM5->EGR=1<<0; //软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效! TIM5->DIER|=1<<1; //允许捕获1中断 TIM5->DIER|=1<<0; //允许更新中断 TIM5->CR1|=0x01; //使能定时器2 MY_NVIC_Init(2,0,TIM5_IRQn,2);//抢占2,子优先级0,组2
中断服务函数:
//中断服务函数//捕获状态,定义一个u8变量TIM5CH1_CAPTURE_STA,表示输入捕获状态//[7]:0,没有成功的捕获;1,成功捕获到一次.//[6]:0,还没捕获到低电平(下降沿);1,已经捕获到低电平(下降沿)了.//[5:0]:捕获高电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294秒)u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 u32 TIM5CH1_CAPTURE_VAL; //输入捕获值(TIM5是32位)//定时器5中断服务程序 void TIM5_IRQHandler(void){ u16 tsr; tsr=TIM5->SR; if((TIM5CH1_CAPTURE_STA&0X80)==0) //还未成功捕获 { if(tsr&0X01) //溢出 { if(TIM5CH1_CAPTURE_STA&0X40) //定时器溢出,说明已经捕获到上升沿,本次捕获的是下降沿 { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次 TIM5CH1_CAPTURE_VAL=0XFFFFFFFF; }else TIM5CH1_CAPTURE_STA++; } } if(tsr&0x02) //CH1发生捕获事件,已经捕获到上升沿,TIMx_CCR1中已捕获到计数器值(IC1上已检测到与所选极性匹配的边沿) { if(TIM5CH1_CAPTURE_STA&0X40) //CC1IF为1,说明已经捕获到了上升沿(第一次捕获上升沿参考else),本次捕获到的是下降沿 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽 TIM5CH1_CAPTURE_VAL=TIM5->CCR1; //获取当前的捕获值.CCR1为上一个输入捕获1事件(IC1)发生时的计数器的值 TIM5->CCER&=~(1<<1); //CC1P=0 设置为上升沿捕获,为下一次捕获做准备 }else //还未开始,第一次捕获上升沿 { TIM5CH1_CAPTURE_STA=0; //清空 TIM5CH1_CAPTURE_VAL=0; //捕获值清零 TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM5->CR1&=~(1<<0) ; //使能定时器2 TIM5->CNT=0; //计数器清空 TIM5->CCER|=1<<1; //CC1P=1 设置为下降沿捕获 TIM5->CR1|=0x01; //使能定时器2 } } } TIM5->SR=0;//清除中断标志位 }