输入捕获简介
输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能。
STM32的输入捕获,简单地说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将此刻定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。
使用TIM2输入捕获的配置步骤:
1、开启TIM2时钟,配置PA0为下拉输入。
需要使用到PA0作为TIM2_CH1上面的脉冲输入。
2、设置TIM2的ARR和PSC ,预分频系数与预装载值
3、设置TIM2的CCMR1
CCMR1寄存器控制着输入捕获1和2的模式,包括映射关系,滤波和分频等。、
4、设置TIM2的CCER,开启输入捕获,并设置为上升沿捕获。
CCER是定时器的开关,并且可以设置输入捕获的边沿。
5、设置TIM2的DIER,使能捕获和更新中断,并编写中断服务函数。
因为我们要捕获的是高电平信号的脉宽。所以,第一次捕获是上升沿,第二次捕获是下降沿。所以必须在捕获上升沿之后,设置捕获边沿就下降沿。同时如果脉宽比较长,那么定时器就会溢出,必须对溢出做处理。这两件事我们都是在中断中实现的,所以这里必须开启捕获中断和更新中断。
6、设置TIM2的CR1,使能定时器
代码如下:
//TIM2_Cap初始化 //arr 自动重装载值 //psc 预分频系数 void TIM2_Cap_Init(u16 arr,u16 psc){ RCC->APB1ENR |= 1<<0; //使能定时器时钟 RCC->APB2ENR |= 1<<2; //使能GPIOA时钟 GPIOA->CRL &= 0xFFFFFFF0;//GPIOA 下拉输入 GPIOA->CRL |= 0x00000008; GPIOA->ODR |= 0<<0; //下拉输入 TIM2->ARR=arr;//自动重装载值 定时器计数到该值的时候发生更新中断 TIM2->PSC=psc;//预分频系数 TIM2->CCMR1 |= 1<<0; //CC1通道被配置为输入,IC1映射到TI1上 TIM2->CCMR1 |= 1<<4; //采样频率,2个事件后生效 TIM2->CCER |= 1<<0; //捕获使能 TIM2->CCER |= 0<<1; //上升沿捕获 TIM2->DIER |= 1<<1; //允许捕获/比较中断 TIM2->DIER |= 1<<0; //允许更新中断 TIM2->CR1 |= 1<<0; //使能计数器 MY_NVIC_Init(2,0,TIM2_IRQn,2); //中断分组 }
如果需要完成一次高电平脉宽的捕获,在完成上升沿捕获之后就需要重新设置捕获的方向,设置成下降沿捕获,当成功完成一次上升沿-下降沿捕获,就可以通过定时器的计数器的值计算出此次捕获的高电平的脉宽。
同时在完成上升沿捕获后,会出现计数器溢出的情况,我们还需要在中断中处理计数器溢出的情况。
所以在定时器中断中我们需要做两件事
1、处理溢出情况
2、上升沿 下降沿之间的转换
有很多种方式,下面是我的处理方式:
//中断处理 u8 TIM2_CAP_STA = 0; u16 TIM2_CAP_VALUE = 0; void TIM2_IRQHandler(void){ u16 INT_IP = TIM2->SR; if(INT_IP&(1<<0)){//溢出 if(TIM2_CAP_STA&0x3F){//脉宽太长 if(TIM2_CAP_STA&0x40){//已经捕获到上升沿 TIM2_CAP_STA |= 1<<7;//设置成功捕获 TIM2_CAP_VALUE = TIM2->CCR1; //获取捕获的值 TIM2->CCER &= 0<<1; //上升沿捕获 TIM2->CCER |= 1<<0; //使能捕获 } else{ TIM2_CAP_STA = 0; TIM2_CAP_VALUE = 0; } } else TIM2_CAP_STA++; } if(INT_IP&(1<<1)){ //捕获 if(TIM2_CAP_STA&0x40){//已经捕获到上升沿 TIM2_CAP_STA |= 1<<7;//设置成功捕获 TIM2_CAP_VALUE = TIM2->CCR1; //获取捕获的值 TIM2->CCER &= 0<<1; //上升沿捕获 TIM2->CCER |= 1<<0; //使能捕获 }else{//还没捕获到上升沿 TIM2_CAP_STA |= 1<<6; //设置捕获到上升沿 TIM2_CAP_VALUE = 0; TIM2->CCER |= 1<<1; //下降沿捕获 TIM2->CNT = 0; //计数器清零 } } TIM2->SR=0;//清除定时器状态(中断标志) }
在中断处理的过程中需要注意两件事:
1、更新中断和捕获中断的处理顺序
2、重新设置为上升沿捕获的书写方式
TIM2->CCER &= 0<<1; //上升沿捕获 TIM2->CCER |= 1<<0; //使能捕获