一、輸入捕獲介紹
二、輸入捕獲配置步驟
(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 }
