TIM输入输出通道是相同引脚
初始化:
- GPIO:对应通道引脚输入
- 时钟 定时器初始化:TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); /
- TIM_Period & TIM_Prescaler & TIM_CounterMode
- 决定了捕获时间的单位
- 输入捕获初始化:TIM_ICInit(TIM5, &TIM5_ICInitStructure);
- TIM_Channel:输入通道
- TIM_ICPolarity= TIM_ICPolarity_Rising;//上升沿捕获
- TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上???猜原因:输入通道直接有联系,可以交叉映射
- TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
- TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
- NVIC
- NVIC_IRQChannel = TIMx_IRQn; //TIM3中断
- 使能自定义功能中断:
- TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断
- 使能定时器 TIM_Cmd(TIMx,ENABLE ); //使能定时器x
捕获时间
原理(以捕获高电平为例):在中断中记录下上升沿到来时被锁存在CCR里的CNT值(或清零CNT),即时修改为捕获下降沿,再记录下下降沿到来的值,结合TIM设置换算出时间。(可能会遇到电平持续时间太长,计数器溢出的情况,此时在中断中判断中断类型....把时间加回)
关键函数:
TIM_GetITStatus(TIM5, TIM_IT_Update)//溢出事件
TIM_GetITStatus(TIM5, TIM_IT_CC1)//捕获事件
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);
VAL=TIM_GetCapture1(TIM5);获得TIM5通道x的锁存值
TIM_SetCounter(TIM5,0);//在捕获到上升沿时清零CNT
中断示例:
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 u16 TIM5CH1_CAPTURE_VAL; //输入捕获值 //定时器5中断服务程序 void TIM5_IRQHandler(void) { if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获 { if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) { if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了 { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了 { TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次 TIM5CH1_CAPTURE_VAL=0XFFFF; }else TIM5CH1_CAPTURE_STA++; } } if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件 { if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次下降沿 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获 }else //还未开始,第一次捕获上升沿 { TIM5CH1_CAPTURE_STA=0; //清空 TIM5CH1_CAPTURE_VAL=0; TIM_SetCounter(TIM5,0); TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获 } } } TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位 }
附录
- TIM_ICInitTypeDef::TIM_ICSelection
这个成员的作用就必须要对照上面的示意图才能明白。仔细看上面的图,可以发现定时器的4个通道并不是完全独立的,而是1、2一组,3、4一组,同组之间的通道是有联系的。也就是可以出现交叉触发。而TIM_ICSelection就是选择要不要使用交叉来触发,如果不明白可以看固件库的说明文档。也就是说,根据不同的取值,可以讲外部引脚的触发信号连到内部不同的单元,这样就使得单片机更加灵活了
- TIM 中断类型
在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存
器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放
了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为
高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储
在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。
以下例子说明如何在TI1输入的上升沿时捕获计数器的值到TIMx_CCR1寄存器中,步骤如下:
● 选择有效输入端:TIMx_CCR1必须连接到TI1输入,所以写入TIMx_CCR1寄存器中的
CC1S=01,只要CC1S不为’00’,通道被配置为输入,并且TIMx_CCR1寄存器变为只读。
● 根据输入信号的特点,配置输入滤波器为所需的带宽(即输入为TIx时,输入滤波器控制位是
TIMx_CCMRx寄存器中的ICxF位)。假设输入信号在最多5个内部时钟周期的时间内抖动,
我们须配置滤波器的带宽长于5个时钟周期;因此我们可以(以fDTS频率)连续采样8次,以确
认在TI1上一次真实的边沿变换,即在TIMx_CCMR1寄存器中写入IC1F=0011。
● 选择TI1通道的有效转换边沿,在TIMx_CCER寄存器中写入CC1P=0(上升沿)。
● 配置输入预分频器。在本例中,我们希望捕获发生在每一个有效的电平转换时刻,因此预
分频器被禁止(写TIMx_CCMR1寄存器的IC1PS=00)。
● 设置TIMx_CCER寄存器的CC1E=1,允许捕获计数器的值到捕获寄存器中。
● 如果需要,通过设置TIMx_DIER寄存器中的CC1IE位允许相关中断请求,通过设置
TIMx_DIER寄存器中的CC1DE位允许DMA请求。
当发生一个输入捕获时:
● 产生有效的电平转换时,计数器的值被传送到TIMx_CCR1寄存器。
● CC1IF标志被设置(中断标志)。当发生至少2个连续的捕获时,而CC1IF未曾被清除,
CC1OF也被置1。
● 如设置了CC1IE位,则会产生一个中断。
● 如设置了CC1DE位,则还会产生一个DMA请求。
为了处理捕获溢出,建议在读出捕获溢出标志之前读取数据,这是为了避免丢失在读出捕获溢
出标志之后和读取数据之前可能产生的捕获溢出信息。