stm32入门——定时器输入捕获实验
实验目的
获得对应GPIO口高电平的持续时间
原理简介
运用中断+定时器的方法,在上升沿到来时触发定时器中断,这是计时的起点;在下降沿时再次触发中断,这是计时的终点。
如上图,寄存器CNT的值从0增长到ARR,等于ARR后再次从0开始计数。在t1时触发上升沿中断,此时CNT的值为CCRX1;在t2时触发下降沿中断,此时CNT的值为CCRX2。t1到t2之间的时间就是到电平持续的时间,示意图中t2 - t1=2*ARR+CCRX2。
对定时器原理不懂的,请参考Systick定时器。
代码讲解
//定时器2通道1输入捕获配置
//arr:自动重装值
//psc:时钟预分频数
void TIM2_Cap_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<0; //TIM2 时钟使能
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRL&=0XFFFFFFF0; //PA0 清除之前设置
GPIOA->CRL|=0X00000008; //PA0 输入
GPIOA->ODR|=0<<0; //PA0 下拉
TIM2->ARR=arr; //设定计数器自动重装值
TIM2->PSC=psc; //预分频器
TIM2->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上
TIM2->CCMR1|=1<<4; //IC1F=0001 配置输入滤波器 以Fck_int采样,2个事件后有效
TIM2->CCER|=0<<1; //CC1P=0 上升沿捕获
TIM2->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
TIM2->DIER|=1<<1; //允许捕获中断
TIM2->DIER|=1<<0; //允许更新中断
TIM2->CR1|=0x01; //使能定时器2
MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
}
时钟和端口A的使能,很基础,不解释。
这里将PA0配置为下拉输入,即PA0无输入时呈现低电平状态。
TIM2->ARR=arr; //设定计数器自动重装值
TIM2->PSC=psc; //预分频器
这两行用来配置定时器的时钟的自动重装载值,是定时器的基础知识。
重点是对CCMR和CCER寄存器的配置。
CCMR寄存器
这个寄存器分为输入和输出两种模式,工作在哪种模式是通过配置CC1S[1:0]来实现的。以I开头的就是输入模式,O开头的就是输出模式。
TIM2->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上
如图,CC1S置为01,即PA0这个通道置为输入、此寄存器工作在输入模式下。IC1应设在TI1上,这是定时器内部的结构,有兴趣的朋友可以去查看一下手册,这里不作过多解释。
TIM2->CCMR1|=1<<4; //IC1F=0001 配置输入滤波器 以Fck_int采样,2个事件后有效
这里是对滤波器的配置,什么是滤波器呢?它就是一个用来确定电平稳定性的东西,比如我们设置的是上升沿触发中断,但有可能由于不可预料的错误,使得PA0上的电平突然高了一下然后又回到了低电平,虽然只高了那么一下,但依旧会触发中断!这就产生了误差!配置滤波器以后可以解决这一问题,图中的N代表采集到N个高电平以后才算是触发了中断,就是说,原先板子只要有了高电平就触发中断,但现在板子要持续检测到N次高电平才触发中断!至于那个f就是采样的频率。
代码中没有对这两位进行设置,默认为零,即滤波过后的有效边沿只要有一个就会捕获一次。如果设置为01,那么要两个滤波后的有效边沿才会捕获。
TIM2->CCER|=0<<1; //CC1P=0 上升沿捕获
TIM2->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
允许捕获计数器的值到捕获寄存器中,就是指发生捕获事件后,当前计时器中的值会直接被送到CCR寄存器中。
TIM2->DIER|=1<<1; //允许捕获中断
TIM2->DIER|=1<<0; //允许更新中断
这是允许两种情况下触发中断,更新中断就是指计数器达到最大值变为0时触发中断,捕获中断就是上升或下降沿时发生捕获事件时产生的中断。
MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
这是设置定时器的优先级和分组,详细内容参考stm32入门——定时器中断和中断优先级简介。
捕获以后的具体操作要看中断函数里了,操作相应寄存器即可。