zoukankan      html  css  js  c++  java
  • STM32 输入捕获的脉冲宽度及频率计算

    输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能。以下是对脉冲宽度及频率的计算。

    1、脉冲宽度

    如下图所示,采集该高电平脉冲的宽度,只需要进入输入捕获上升沿检测,记录当前的发生上升沿时的CNT值,再进行输入捕获下降沿检测,也记录当前发生下降沿时的CNT值,两次CNT值的差值再根据计数的频率就可以算出脉冲的宽度。

    上升沿及下降沿捕获的程序具体实现如下:

    TIM8_Cap_Init(0XFFFF,72-1);                                          //以1Mhz的频率计数 
    
    void TIM8_UP_IRQHandler(void)
    { 
     	if((TIM8CH4_CAPTURE_STA&0X80)==0)                            //还未成功捕获	
    	{	  
    		if (TIM_GetITStatus(TIM8,TIM_IT_Update) != RESET)
    		{	    
    			if(TIM8CH4_CAPTURE_STA&0X40)                 //已经捕获到高电平了
    			{
    				if((TIM8CH4_CAPTURE_STA&0X3F)==0X3F) //高电平太长了
    				{
    					TIM8CH4_CAPTURE_STA|=0X80;   //标记成功捕获了一次
    					TIM8CH4_CAPTURE_VAL=0XFFFF;
    				}
    				else 
    					TIM8CH4_CAPTURE_STA++;       //捕获高电平后定时器溢出的次数++
    			}	 
    		}
    						   
     	}
    	TIM_ClearITPendingBit(TIM8,TIM_IT_Update);                  //清除中断标志位
    }
    void TIM8_CC_IRQHandler(void)
    {
       if((TIM8CH4_CAPTURE_STA&0X80)==0)
       {
    	   if(TIM_GetITStatus(TIM8,TIM_IT_CC4) != RESET)           //捕获1发生捕获事件
    		{	
    			     if(TIM8CH4_CAPTURE_STA&0X40)          //捕获到一个下降沿 		
    				{	  			
    					TIM8CH4_CAPTURE_STA|=0X80;//标记成功捕获到一次高电平脉宽
    					TIM8CH4_CAPTURE_VAL=TIM_GetCapture4(TIM8);
    			   		TIM_OC4PolarityConfig(TIM8,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
    				}
    				else  				  //还未开始,第一次捕获上升沿
    				{
    					TIM8CH4_CAPTURE_STA=0;	  //清空
    					TIM8CH4_CAPTURE_VAL=0;
    		 			TIM_SetCounter(TIM8,0);   //计数器清零
    					TIM8CH4_CAPTURE_STA|=0X40;//标记捕获到了上升沿
    			   		TIM_OC4PolarityConfig(TIM8,TIM_ICPolarity_Falling);//CC1P=1 设置为下降沿捕获
    				}		    	    	    
    		}
       }
        TIM_ClearITPendingBit(TIM8, TIM_IT_CC4);                      //清除中断标志位
    
    

    程序中定时器输入捕获配置的TIM8CH4通道,CNT计数的频率1MHZ,即计数1个就是1us。TIM8_UP_IRQHandler是一个定时中断函数,根据TIM8_Cap_Init(0XFFFF,72-1)可知65536us会中断一次,所以总的脉冲宽度时间如下:

    temp=TIM8CH4_CAPTURE_STA&0X3F;      //从TIM8_UP_IRQHandler中断知中捕获上升沿及下降沿期间进行此中断的次数
    temp*=65536;//溢出时间总和
    temp+=TIM8CH4_CAPTURE_VAL;          //得到总的高电平时间  TIM8CH4_CAPTURE_VAL为CNT计数的值
    

    2、频率测量

    如下图所示,测量脉冲的频率,则分别采集两次输入捕获上升沿的CNT值,脉冲的频率=f/△CNT

    两次上升沿捕获的程序具体实现如下:

    TIM8_Cap_Init(0XFFFF,72-1);    //以1Mhz的频率计数
    
    void TIM8_CC_IRQHandler(void)
    {
       if(TIM_GetITStatus(TIM8,TIM_IT_CC4)!=RESET)
       {
    	   TIM_ClearITPendingBit(TIM8, TIM_IT_CC4);    //清除中断标志位
               if(state==0)    //捕获第一个上升沿
               {
                   state=1;
    	       timecount=TIM_GetCapture4(TIM8);        //记录第一次上升沿的CNT值
    	   }
    	   else if(state==1)//捕获第二个上升沿
    	   {
                      state=0;
    		  timecount1=TIM_GetCapture4(TIM8);   //记录第二次上升沿的CNT值
                   if(timecount<timecount1)
                   {
                     test=timecount1-timecount;           //两次上升沿的差值
    	       }
    	       else if(timecount>timecount1)
    	       {
                     test=(0xffff-timecount)+timecount1;  //两次上升沿的差值
    	       }
    	       else
    	         test=0;
    
    	         fq=1000000/test;                     //脉冲的频率
    	   }
       }
    }
    

    由程序可知配置的定时器的输入捕获的计数的频率为1MHZ,两次捕获上升沿的差值test为计数器CNT计的次数,所以总的周期即为T=1us*test,所以频率就fq=1000000/test HZ;

    另外,测量频率除了还可以使用定时器的外部脉冲信号计数来进行。

    3、定时器的外部计数模式测频率

    因为STM32有外部时钟源模式,即可以根据外部脉冲信号进行计数,然后另外设定定时器定时中断去读取计数器的值,频率=CNT/定时中断时间。程序代码实现如下:

    TIM3_Int_Init(9999,7199);    //定时1s中断一次  
    TIM2_Cap_Init();             //外部信号引脚脉冲检测 TIM2_CH1_ETR
    void TIM2_Cap_Init(void)                                        //配置 TIM2_CH1_ETR 为外部脉冲计数
    {	 
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//使能TIM2时钟
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA时钟
    	
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;              //PA0 清除之前设置  
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;           //PA0 输入  
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	GPIO_ResetBits(GPIOA,GPIO_Pin_0);                       //PA0 下拉
    	
    	//初始化定时器2 TIM2	 
    	TIM_TimeBaseStructure.TIM_Period = 0xFFFF;              //设定计数器自动重装值 
    	TIM_TimeBaseStructure.TIM_Prescaler =0; 	        //预分频器   
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);         //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
      	TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF);          //配置外部触发,否则不会计数
    	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
    	TIM_SetCounter(TIM2, 0); 		
      	TIM_Cmd(TIM2,ENABLE ); 	                                //使能定时器2
    
    }
    /*******************************************************************************
     * 名称: TIM3_IRQHandler
     * 功能: 通用定时器3中断服务函数
     * 形参: 无
     * 返回: 无
     * 说明: 1S定时中断一次
     ******************************************************************************/
    void TIM3_IRQHandler(void)
    {
    	if(TIM_GetITStatus(TIM3,TIM_IT_Update)!= RESET)      //检查TIM3更新中断发生与否
    	{
    	        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除TIMx更新中断标志 
    		 
    		CNT=TIM_GetCounter(TIM2);                   //读取1s内计数器计的CNT值
                    fq=CNT;                                     //脉冲的频率
    		TIM_SetCounter(TIM2,0);
            }
    }
    
    

    因为知道定时中断时间为1s,所以测量的频率fq=CNT/1(HZ),频率的计算及脉冲宽度的测量有以上方法测试。

    by 羊羊得亿
    2017-02-24 ShenZhen

  • 相关阅读:
    Codeforces 834D The Bakery
    hdu 1394 Minimum Inversion Number
    Codeforces 837E Vasya's Function
    Codeforces 837D Round Subset
    Codeforces 825E Minimal Labels
    Codeforces 437D The Child and Zoo
    Codeforces 822D My pretty girl Noora
    Codeforces 799D Field expansion
    Codeforces 438D The Child and Sequence
    Codeforces Round #427 (Div. 2) Problem D Palindromic characteristics (Codeforces 835D)
  • 原文地址:https://www.cnblogs.com/yangxuli/p/6434508.html
Copyright © 2011-2022 走看看