输入捕获

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); //清除中断标志位
 
}
View Code

附录

  • 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请求。
为了处理捕获溢出,建议在读出捕获溢出标志之前读取数据,这是为了避免丢失在读出捕获溢
出标志之后和读取数据之前可能产生的捕获溢出信息。

posted @ 2014-03-20 00:22  熄灯就睡  阅读(941)  评论(0编辑  收藏  举报