原理:首先设置定时器通道 x 为 上升沿捕获,这样,t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x 为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。这样, 根据定时器的计数频率,我们就可以算出 t1~t2 的时间,从而得到高电平脉宽。
首先需要使能TIM时钟通道CHX对应的IO口(设置为输入下拉),按照前面的一样设置PSC以及ARR(为了算出计数频率,以及PWM周期),
TIMX_CCMR1
上面一行对应的是CH1和CH2的比较模式,下面一行用于CH1和CH2的捕获模式
CC1S[1:0] = 01,配置为输入,三种方式如图所示,所以为IC会被映射到T1,T2,TRC三个通道上。
IC1PSC[1:0]:我们设置为一次边沿就触发一次中断(因为上升沿和下降沿都需要进行捕获)
IC1F[3:0]配置输入采样的频率和数字滤波器长度(开启为了滤波的作用),这里设置0000就行,只需要采集到上升沿就会触发捕获
捕获使能寄存器TIMX_CCER
CC1E必须设置为1,进行捕获使能,CC1P的数值因情况而定,看需要捕获的是什么信号。
因为需要当捕获完上升沿信号的时候,会溢出,接着需要捕获下降沿信号,所以需要在溢出后产生中断,在中断中进行切换操作,所以需要使能中断寄存器(TIMX_DIER)
所以CC1IE设置为1就ok了
紧接着需要使能定时器TIMX_CR1
当配置为输入的时候,可以捕获到当捕获发生时候的CNT的数值。捕获到一次上升沿的数值和一次下降沿的数值,两者之差就是一次高电平的脉宽。
配置完后需要对中断代码进行理解
//捕获状态
//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到高电平;1,已经捕获到高电平了.
//[5:0]:捕获高电平后溢出的次数
u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM2CH1_CAPTURE_VAL; //输入捕获值
//定时器2中断服务程序
void TIM2_IRQHandler(void)
{
u16 tsr;
tsr=TIM2->SR;
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(tsr&0X01)//溢出
{
if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM2CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
TIM2CH1_CAPTURE_VAL=0XFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}
if(tsr&0x02)//捕获1发生捕获事件
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM2CH1_CAPTURE_VAL=TIM2->CCR1; //获取当前的捕获值.
TIM2->CCER&=~(1<<1); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA=0X40; //标记捕获到了上升沿
TIM2->CNT=0; //计数器清空
TIM2->CCER|=1<<1; //CC1P=1 设置为下降沿捕获
}
}
}
TIM2->SR=0;//清除中断标志位
}
当第一次捕获到上升沿电平的时候,会将CNT,TIM2CH1_CAPTURE_VAL,的数值清空,且将第7位设置位1,当捕获完成是第八位置为1,然后将其设置为下降沿捕获,但上升沿捕获和下降沿捕获之间可能差着n个PWM周期,所以自然会产生多次溢出,这里就需要把每次的溢出次数保存并且累加起来,然后借助计数周期算出高电平的脉宽,(因为当捕获切换的时候,可能会多次溢出,更新中断),计数频率是1us一次,所以n*ARR+CCRX2的数值便是高电平的脉宽时间。