1、通用定時器輸入捕獲功能簡介
通用定時器的輸入捕獲模式可以用來測量脈沖寬度或者測量頻率。
STM32的每個通用定時器都有4個輸入捕獲的通道,分別是TIMx_CH1、TIMx_CH2、TIMx_CH3、TIMx_CH4。
STM32通過檢測通道上的邊沿信號,在邊沿信號發生變化時(上升沿或下降沿變化),將當前定時器計數器的值(寄存器TIMx_CNT的值)存放到對應通道的捕獲/比較寄存器TIMx_CCRx里面,通過記錄兩次邊沿信號的時間,來計算脈沖寬度或頻率。
2、通用定時器輸入捕獲詳解
通用定時器框圖如下:
圖中紅色框部分就是通用定時器的輸入捕獲功能。
TIMx_CH1、TIMx_CH2、TIMx_CH3、TIMx_CH4分別對應通用定時器的4個輸入捕獲通道。
從通用定時器框圖可以看到每路輸入捕獲通道的結構都是差不多的。
以CH1為例,通用定時器通過TIMx_CH1腳位產生信號TI1,TI1經過濾波器后,將信號傳輸給邊沿檢測器,邊沿檢測器檢測到准確的邊沿信號之后,產生TI1FP1和TI1FP2信號(這兩個信號其實是一樣的,只是輸出的路徑不一樣),TI1FP1信號提供給IC1,IC1經過預分頻器之后,產生捕獲信號,這時候定時器計數器的當前值被鎖存到捕獲/比較寄存器中,而且TIMx_SR狀態寄存器的CC1IF標志位被置1,如果使能了通道1輸入捕獲的中斷功能,就會產生中斷。
在紅色的框圖中,TI1的輸入可以選擇TIMx_CH1、TIMx_CH2、TIMx_CH3這3個通道的異或,這個功能好像是高級定時器的霍爾傳感器功能,這里不用管,用作輸入捕獲功能的時候T1就默認選擇TIMx_CH1輸入就好。
輸入濾波器:
輸入捕獲通道通過設置TIMx_CCMRx捕獲/比較模式寄存器的ICxF[3:0]位來配置濾波器。
這里需要注意的是,輸入捕獲有4個通道,而捕獲/比較模式寄存器只有兩個,分別是TIMx_CCMR1和TIMx_CCMR2,通道1由TIMx_CCMR1的低8位配置;通道2由TIMx_CCMR1的高8位配置;通道3由TIMx_CCMR2的低8位配置;通道4由TIMx_CCMR2的高8位配置。
還要注意的是,捕獲/比較模式寄存器在不同狀態下時,配置的功能是不一樣,如果通道被配置成輸出,那么捕獲/比較模式寄存器是用來配置輸出功能;如果通道被配置成輸入,則捕獲/比較模式寄存器是用來配置輸入功能。捕獲/比較模式寄存器TIMx_CCMRx的CCxS[1:0]位用來配置通道是輸出還是輸入。當CCxS[1:0] = 00時,通道被配置為輸出。當CCxS[1:0] != 0時,通道被配置為輸入。
下圖是通道1的IC1F[3:0]位的寄存器說明圖:
圖中的FCK_INT是定時器的輸入頻率,一般是MCU的主頻(要看具體的設置)。而FDTS是根據TIMx_CR1控制寄存器的bit9~bit8位CKD[1:0]的值來確定:
當CKD = 00時,FDTS = FCK_INT。
當CKD = 00時,FDTS = 2*FCK_INT。
當CKD = 00時,FDTS = 4*FCK_INT。
圖中的N是指濾波長度,假設IC1F[3:0] = 0011,並設置IC1映射到通道1上,且為上升沿觸發,那么在捕獲到上升沿的時候,再以FCK_INT的頻率,連續采樣8次通道1的電平,如果都是高電平,則說明這是一個有效的觸發信號。
濾波器可以濾除哪些脈寬低於一定時間的脈沖信號,從而達到濾波的效果,當然也可以選擇不濾波。
邊沿檢測器:
邊沿檢測器可以檢測信號是上升沿還是下降沿,只有跟設定的邊沿對得上的信號才能觸發輸入捕獲功能。
邊沿檢測器可以設定為上升沿觸發或是下降沿觸發,這是通過捕獲/比較使能寄存器TIMx_CCER的CCxP位來選擇的。
同樣CCxP的位在通道位輸入和輸出是具有不同的配置功能。當通道設為輸入時,CCxP用來設置邊沿檢測器。
當CCxP = 0是,輸入捕獲是在上升沿的時候觸發。
當CCxP = 1時,輸入捕獲是在下降沿的時候觸發。
TIxFPx信號:
從通用定時器框圖中可以看到,信號在經過輸入濾波器和邊沿檢測器之后,每個通道都會產生2個信號:
通道1:TI1FP1和TI1FP2。
通道2:TI2FP1和TI2FP2
通道3:TI3FP1和TI3FP2
通道4:TI4FP1和TI4FP2
其實TIxFP1和TIxFP2的信號是同一個,但是他們輸出的方向不一樣,所以用不同的名稱來區分,從圖中可以看出:
TI1FP1作為輸入源提供給IC1,而TI1FP2作為輸入源提供給IC2。
TI2FP1作為輸入源提供給IC2,而TI2FP2作為輸入源提供給IC1。
TI3FP1作為輸入源提供給IC3,而TI3FP2作為輸入源提供給IC4。
TI4FP1作為輸入源提供給IC4,而TI4FP2作為輸入源提供給IC3。
也就是說TIMx_CH1和TIMx_CH2的輸入信號是可以交互到IC1和IC2的;TIMx_CH3和TIMx_CH4的輸入信號也可以交互到IC3和IC4。
具體ICx的輸入源的選擇是通過捕獲/比較寄存器TIMx_CCMRx的CCxS[1:0]位決定的,比如IC1的輸入源的選擇:
當CC1S[1:0] = 00時,通道1被配置為輸出。
當CC1S[1:0] = 01時,通道1被配置為輸入,IC1的輸入源選擇TI1FP1。
當CC1S[1:0] = 10時,通道1被配置為輸入,IC1的輸入源選擇TI2FP2。
當CC1S[1:0] = 11時,通道1被配置為輸入,IC1的輸入源選擇TRC。
其它通道的配置也是類似的,可以參照着查看參考手冊。
預分頻器:
輸入捕獲的預分頻器是通過TIMx_CCMRx的ICxPSC[1:0]位配置的。
當ICxPSC[1:0] = 00時,無預分頻,捕獲輸入口上檢測到的滅一個邊沿都觸發一次捕獲。
當ICxPSC[1:0] = 01時,捕獲輸入口上檢測到2個邊沿才觸發一次捕獲。
當ICxPSC[1:0] = 10時,捕獲輸入口上檢測到4個邊沿才觸發一次捕獲。
當ICxPSC[1:0] = 11時,捕獲輸入口上檢測到8個邊沿才觸發一次捕獲。
捕獲輸入中斷:
當輸入捕獲成功之后,計數器的值(TIMx_CNT)被傳送到TIMx_CCRx寄存器,並且狀態寄存器TIMx_SR的相應通道位CCxIF標志被置位,如果相應的中斷使能控制位被置位,則會產生中斷。
當CCxIF標志位被置位時,如果不清楚CCxIF標志位,則再次捕獲成功之后,會將狀態寄存器TIMx_SR的相應通道位CCxOF置位,指示通道重復捕獲。
3、通用定時器輸入捕獲的配置流程
首先需要先打開定時器和通道IO口的時鍾。將通道IO口配置成復用輸入,具體是配置成上拉輸入或下拉輸入還是懸空,根據具體需求來設定。
設置定時器的計數頻率,當產生捕獲時,用來計時,需要注意定時器溢出的問題,當定時器溢出之后,會清除定時器計數器的值(向上計數)或重新賦值初值(向下計數),在計算捕獲時間的時候,如果有溢出,需要加上溢出的時間。
通過捕獲/比較模式寄存器TIMx_CCMRx配置通道為輸入模式,配置映射關系(即選擇ICx的輸入源),配置濾波器,配置輸入捕獲的預分頻器。
通過捕獲/比較使能寄存器TIMx_CCER來選擇輸入捕獲的邊沿信號,是上升沿觸發還是下降沿觸發。在使用輸入捕獲功能之前,必須先使能,而輸入捕獲的使能是通過置位捕獲/比較使能寄存器TIMx_CCER的相應位來實現的。
通過DMA/中斷使能寄存器TIMx_DIER使能相應的中斷。
最后通過控制寄存器TIMX_CR1使能定時器,讓定時器開始計數。
4、HAL庫操作通用定時器的輸入捕獲功能
以配置TIM3的通道1為例,TIM3的通道1對應的腳位是PA6,初始化代碼如下:
1 TIM_HandleTypeDef TIM3_Handler_Init; 2 TIM_IC_InitTypeDef CAPTURE_Handler_Init; 3
4 void CAPTURE_Init(void) 5 { 6 GPIO_InitTypeDef GPIO_InitStruct; 7
8 __HAL_RCC_GPIOA_CLK_ENABLE(); 9 __HAL_RCC_TIM3_CLK_ENABLE(); 10
11 GPIO_InitStruct.Pin = GPIO_PIN_6; 12 GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT; 13 GPIO_InitStruct.Pull = GPIO_PULLDOWN; 14 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 15 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 16
17 TIM3_Handler_Init.Instance = TIM3; 18 TIM3_Handler_Init.Init.Prescaler = 72-1; //分頻為1MHZ
19 TIM3_Handler_Init.Init.Period = 50000; //定時50ms
20 TIM3_Handler_Init.Init.CounterMode = TIM_COUNTERMODE_UP; 21 HAL_TIM_Base_Init(&TIM3_Handler_Init); 22
23 CAPTURE_Handler_Init.ICPolarity = TIM_ICPOLARITY_RISING; 24 CAPTURE_Handler_Init.ICPrescaler = TIM_ICPSC_DIV1; 25 CAPTURE_Handler_Init.ICSelection = TIM_ICSELECTION_DIRECTTI; 26 CAPTURE_Handler_Init.ICFilter = 0; 27 HAL_TIM_IC_ConfigChannel(&TIM3_Handler_Init,&CAPTURE_Handler_Init,TIM_CHANNEL_1); 28
29 HAL_TIM_IC_Start_IT(&TIM3_Handler_Init,TIM_CHANNEL_1); 30
31 HAL_TIM_IC_Start(&TIM3_Handler_Init,TIM_CHANNEL_1); 32
33 HAL_NVIC_SetPriority(TIM3_IRQn,2,1); 34 HAL_NVIC_EnableIRQ(TIM3_IRQn); 35 }
第1、2行是定義TIM3和輸入捕獲的句柄變量。
第6到第15行是打開TIM3和IO口的時鍾,並且配置IO口的狀態。
第17到第21行是配置TIM3的計數時鍾(多少時間計數器計數一次)、計數周期(多久溢出)和計數方式(向上或向下或中央對齊模式)。
第23行是選擇邊沿觸發信號,這里選上升沿觸發。
第24行是選擇輸入捕獲分頻器的系數,這里選擇1分頻,也就是不分頻。
第25行是選擇通道的映射,即選擇ICx的輸入源,這里選擇TI1作為IC1的輸入源。
第26行是選擇輸入捕獲的濾波器,這里選擇不濾波。
第27行是通過HAL_TIM_IC_ConfigChannel()函數初始化相應的輸入捕獲通道。
第29行是通過HAL_TIM_IC_Start_IT()函數使能輸入捕獲的中斷功能,如果不使能則無法進入中斷。
第31行是通過HAL_TIM_IC_Start()函數使能輸入捕獲功能,這樣輸入捕獲的功能才會被打開,這個函數還是能了通用定時器,讓通用定時器開始工作。