(stm32f103學習總結)—輸入捕獲模式


一、輸入捕獲介紹

 在定時器中斷實驗章節中我們介紹了通用定時器具有多種功能,輸入捕獲就是其中一種。STM32F1 除了基本定時器 TIM6 和 TIM7,其他定時器都具有輸入捕獲功能。輸入捕獲可以對輸入的信號的上升沿,下降沿或者雙邊沿進行捕獲,通常用於測量輸入信號的脈寬、測量 PWM 輸入信號的頻率及占空比。
  輸入捕獲的工作原理比較簡單,在輸入捕獲模式下,當相應的 ICx 信號檢測到跳變沿后,將使用捕獲/比較寄存器(TIMx_CCRx)來鎖存計數器的值。簡單的說就是通過檢測 TIMx_CHx 上的邊沿信號,在邊沿信號發生跳變(比如上升沿/下降沿)的時候,將當前定時器的值(TIMx_CNT)存放到對應的通道的捕獲/比較寄存(TIMx_CCRx)里面,完成一次捕獲。同時還可以配置捕獲時是否觸發中斷/DMA 等。下面我們以輸入捕獲測量脈寬為例,通過一個簡圖來介紹輸入捕獲的工作原理,如圖 所示:
  從上圖可以看出,t1-t2 時間就是我們需要測量的高電平時間,假如定時器工作在向上計數模式,測量方法是:首先設置定時器通道 x 為上升沿捕獲,這樣在 t1 時刻,就會捕獲到當前的 CNT 值,然后立即清零 CNT,並設置通道 x 為下降沿捕獲,這樣到 t2 時刻,又會發生捕獲事件,得到此時的 CNT 值,記為 CCRx2。根據定時器的計數頻率,我們就可以算出 t1-t2 的時間,從而得到高電平脈寬。在 t1-t2 時間內可能會出現 N 次定時器溢出,因此我們還需要對定時器溢出進行處理,防止因高電平時間過長發生溢出導致測量數據不准。CNT計數的次數等於:N*ARR+CCRx2,有了這個計數次數,再乘以 CNT 的計數周期,即可得到 t2-t1 的時間長度,即高電平持續時間。

二、輸入捕獲配置步驟

(1)使能定時器及端口時鍾,並設置引腳復用器映射和引腳模式等

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;

 

 

(2)初始化定時器參數,包含自動重裝值,分頻系數,計數方式等

  TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(3)設置通用定時器的輸入捕獲參數,開啟輸入捕獲功能

  TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

(4)開啟捕獲和定時器溢出(更新)中斷

  TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)

(5)設置定時器中斷優先級,使能定時器中斷通道 NVIC初始化庫函數是

  NVIC_Init()

(6)使能定時器

  TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

(7)編寫定時器中斷服務函數

  void TIM5_IRQHandle()

三、代碼舉例

所要實現的功能是:使用TIM5的CH1檢測輸入信號高電平脈寬, 將檢測的高電平脈寬時間通過printf函數打印出來,同時讓D1指示燈不 斷閃爍表示系統正常運行。(使用普中stm32f103開發板)

 1 #ifndef _input_H  2 #define _input_H
 3 
 4 #include "system.h"
 5 
 6 extern u8 TIM5_CH1_CAPTURE_STA; //輸入捕獲的狀態
 7 extern u16 TIM5_CH1_CAPTURE_VAL;//輸入捕獲值
 8 
 9 
10 void TIM5_CH1_Input_Init(u16 arr,u16 psc); 11     
12 #endif

 

 

(原子開發板資料)

bit7位置1時表示成功捕獲完一次高電平(按鍵按下直到抬起整個過程結束);代碼58、66、79

bit6位置1時表示獲得高電平的標志位,(表示按鍵已經按下)代碼62、77、87

bit0~5位表示高電平時間是定時器溢出的次數(即在按鍵按下時定時器溢出幾次)

如果溢出次數超過了6位所能表示的范圍時怎么辦?

  代碼64—68解決辦法

就是在TIM5_CH1_CAPTURE_STA==0x3f 時將 TIM5_CH1_CAPTURE_STA變量強制bit7置1(即強制捕獲完成去執行主函數代碼27以后的代碼段,然后重新進行下一次的捕獲)   TIM5_CH1_CAPTURE_STA|=0x80;

 1 #include "input.h"
 2 
 3 u8 TIM5_CH1_CAPTURE_STA; //輸入捕獲狀態 
 4 u16 TIM5_CH1_CAPTURE_VAL;//輸入捕獲值
 5 
 6 /*******************************************************************************  7 * 函 數 名 : TIM5_CH1_Input_Init  8 * 函數功能 : TIM5_CH1輸入捕獲初始化函數  9 * 輸 入 : arr:自動重裝載值 10  psc:預分頻系數 11 * 輸 出 : 無 12 *******************************************************************************/
13 void TIM5_CH1_Input_Init(u16 arr,u16 psc) 14 { 15  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; 16  TIM_ICInitTypeDef TIM_ICInitStructure; 17  NVIC_InitTypeDef NVIC_InitStructure; 18  GPIO_InitTypeDef GPIO_InitStructure; 19     
20  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 21     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5時鍾
22     
23     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//管腳設置
24     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;     //設置下拉輸入模式
25     GPIO_Init(GPIOA,&GPIO_InitStructure);        /* 初始化GPIO */
26     
27     TIM_TimeBaseInitStructure.TIM_Period=arr;   //自動裝載值
28     TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分頻系數
29     TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 30     TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //設置向上計數模式
31     TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure); 32     
33     TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道1
34     TIM_ICInitStructure.TIM_ICFilter=0x00;  //濾波
35     TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕獲極性
36     TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分頻系數
37     TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1
38     TIM_ICInit(TIM5,&TIM_ICInitStructure); 39     TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE); 40     
41     NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//中斷通道
42     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//搶占優先級
43     NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;        //子優先級
44     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
45     NVIC_Init(&NVIC_InitStructure); 46         
47     TIM_Cmd(TIM5,ENABLE); //使能定時器
48 } 49 
50 /******************************************************************************* 51 * 函 數 名 : TIM5_IRQHandler 52 * 函數功能 : TIM5中斷函數 53 * 輸 入 : 無 54 * 輸 出 : 無 55 *******************************************************************************/
56 void TIM5_IRQHandler(void) 57 { 58     if((TIM5_CH1_CAPTURE_STA&0x80)==0) //還未成功捕獲
59  { 60         if(TIM_GetITStatus(TIM5,TIM_IT_Update)) //發生更新中斷
61  { 62             if(TIM5_CH1_CAPTURE_STA&0X40)//捕獲到了高電平
63  { 64                 if((TIM5_CH1_CAPTURE_STA&0x3f)==0x3f) //高電平時間太長
65  { 66                     TIM5_CH1_CAPTURE_STA|=0x80; //標志一次捕獲成功
67                     TIM5_CH1_CAPTURE_VAL=0xffff; 68  } 69                 else
70  { 71                     TIM5_CH1_CAPTURE_STA++; 72  } 73  } 74  } 75         if(TIM_GetITStatus(TIM5,TIM_IT_CC1)) //發生捕獲中斷
76  { 77             if(TIM5_CH1_CAPTURE_STA&0X40)//捕獲到了高電平
78  { 79                 TIM5_CH1_CAPTURE_STA|=0x80; //成功捕獲一次高電平
80                 TIM5_CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); 81                 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //設置上升沿捕獲
82  } 83             else
84  { 85                 TIM5_CH1_CAPTURE_STA=0; 86                 TIM5_CH1_CAPTURE_VAL=0; 87                 TIM5_CH1_CAPTURE_STA|=0x40; //捕獲到高電平標志
88  TIM_Cmd(TIM5,DISABLE); 89                 TIM_SetCounter(TIM5,0); //定時器初值為0
90                 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //設置下降沿捕獲
91  TIM_Cmd(TIM5,ENABLE); 92  } 93  } 94  } 95     TIM_ClearITPendingBit(TIM5,TIM_IT_CC1|TIM_IT_Update); 96 }

 

 

 1 #include "system.h"
 2 #include "SysTick.h"
 3 #include "led.h"
 4 #include "usart.h"
 5 #include "input.h"
 6 
 7 
 8 /*******************************************************************************  9 * 函 數 名 : main 10 * 函數功能 : 主函數 11 * 輸 入 : 無 12 * 輸 出 : 無 13 *******************************************************************************/
14 int main() 15 { 16     u8 i=0; 17     u32 indata=0; 18     
19     SysTick_Init(72); 20     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中斷優先級分組 分2組
21  LED_Init(); 22     USART1_Init(9600); 23     TIM5_CH1_Input_Init(0xffff,71);  //以1M頻率計數
24     
25     while(1) 26  { 27         if(TIM5_CH1_CAPTURE_STA&0x80) //成功捕獲
28  { 29             indata=TIM5_CH1_CAPTURE_STA&0x3f; 30             indata*=0xffff; //溢出次數乘以一次的計數次數時間 us
31             indata+=TIM5_CH1_CAPTURE_VAL;//加上高電平捕獲的時間
32             printf("高電平持續時間:%d us\r\n",indata); //總的高電平時間
33             TIM5_CH1_CAPTURE_STA=0; //開始下一次捕獲
34  } 35         
36         i++; 37         if(i%20==0) 38  { 39             led1=!led1; 40  } 41         delay_ms(10); 42  } 43 }

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM