STM32通用定时器做输入捕捉(具体时间计算)

                                                                                任务:输入捕获 脉冲测距。

 

        STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能。    

       STM32定时器检测是否有信号,若有信号(上升沿),则定时器开始计时,直至检测到下降沿计时结束。这期间的脉宽长度*定时器的检测频率(定时器初始化时配置好的)即为实际的时长。 实际的时长*声速=距离

TIM_TimeBaseStructure.TIM_Period=65536-1;         定时器计数达到65535后溢出

TIM_TimeBaseStructure.TIM_Prescaler=7200-1;      预分频值,实际检测频率为72000 000/7200=10 000Hz,周期为100us。   每100us+1。 

            定时器触发一次的时间为:(7200/72000 000)*65536

            定时器中断函数:

void TIM2_IRQHandler(void)   
{
	
	  if((TIM2CH1_CAPTURE_STA&0X80)==0)//未捕获                   1000 0000 
    {
        if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET) 
        {
            if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平            0100 0000
            {
                if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//溢出处理       0011 1111
                { 
                    TIM2CH1_CAPTURE_STA|=0X80;//标记成功捕获一次      1000 0000 
                    TIM2CH1_CAPTURE_VAL=0XFFFF;
                }else TIM2CH1_CAPTURE_STA++;
            }
        }
         
        if(TIM_GetITStatus(TIM2,TIM_IT_CC1) !=RESET)          //捕获到上升沿中断
        {
            if(TIM2CH1_CAPTURE_STA & 0x40)  //捕获到一个下降沿             0100 0000
            {
                TIM2CH1_CAPTURE_STA|=0X80;  //标记成功捕获到一次上升沿     1000 0000 
                TIM2CH1_CAPTURE_VAL = TIM_GetCounter(TIM2);
                TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 设置上升沿捕获
            }
            else
            {                                     //还没有捕获到新的上升沿
                TIM2CH1_CAPTURE_STA=0;            //清空
                TIM2CH1_CAPTURE_VAL=0;
                 
                TIM_SetCounter(TIM2,0);
                TIM2CH1_CAPTURE_STA|=0X40;        //标记捕获到了上升沿     0100 0000
                TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);        //CC1P=1 设置为下降沿捕获
            }
        }
         
    }
    TIM_ClearITPendingBit(TIM2,TIM_IT_CC1|TIM_IT_Update); /*清除中断标志位*/
}

捕获基本思路:

        首先设置两个变量Capture_State和Capture_Value。 其中 Capture_State,是用来记录捕获状态,该变量类似一个寄存器(其实就是个变量,只是我们把它当成一个寄存器那样来使用)。 另外一个变量 Capture_Value,则用来记录捕获到下降沿的时候,TIM2_CNT的值。现在我们来介绍一下,捕获高电平脉宽的思路:首先,设置 TIM2_CH1 捕获上升沿(这在TIM2的初始化函数执行的时候就设置好了),然后等待上升沿中捕获断到来,当捕获到上升沿中断,此时如果 Capture_State的第 6 位为 0,则表示还没有捕获到新的上升沿,就先把 Capture_State、Capture_Value和 TIM2->CNT 等清零,然后再设置 Capture_State的第 6 位为 1,标记捕获到高电平,最后设置为下降沿捕获,等待下降沿到来。如果等待下降沿到来期间,定时器发生了溢出,就在Capture_State里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记 捕获完成 (虽然此时还没有捕获到下降沿 )。 当下降沿到来的时候,先设置Capture_State的第 7 位为 1,标记成功捕获一次高电平,然后读取此时的定时器的捕获值到 Capture_Value里面,最后设置为上升沿捕获,回到初始状态。 这样,我们就完成一次高电平捕获了,只要 Capture_State的第 7 位一直为 1,那么就不会进行第二次捕获,我们在main函数处理完捕获数据后,将Capture_State置零,就可以开启第二次捕获。

主函数: 

主要的宗旨就是: TIM2 的计数频率(根据TIM_Prescaler计算得来 每一次计数的时长)*高电平脉宽(计数个数)=  准确高电平持续时间。


  while(1)
  {
    
		 if(TIM2CH1_CAPTURE_STA&0X80)//成功捕获一次上升沿
		{
				temp=TIM2CH1_CAPTURE_STA&0X3F;
				temp*=65536;/溢出时间总和          //对应和TIM_Period一致 TIM是16位的 最大即为65536
				temp+=TIM2CH1_CAPTURE_VAL;//总计数总和
		  if(temp>1000)             //省去一些干扰信号
				{
					printf("电平持续时间:%d us     ",temp*100);//us
					printf("%d ms     ",temp/10);//ms
					printf("%d s     ",temp/10000);//s
					printf("\r\n距离: 1500 m/s * %d ms= %dm\r\n",temp/10,temp*15/100);//s
					printf("\r\n");//空行
				}
  			
				TIM2CH1_CAPTURE_STA=0;/开启下一次捕获
		}
   }

(错误思路:通过TIM_Period和TIM_Prescaler把TIM时间算出来,乘以统计的数据temp)和代码中temp*=65536重复。

另外注意TIM2_IRQn对应的PA0引脚,工作模式为下拉输入。 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 

 

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值