有人使用STM32G4系列的通用型TIMER基于捕獲功能對外來信號進行周期及占空比的測量。他用TIM3產生頻率、占空比可調的PWM輸出做為被測信號。TIM4用來進行頻率測量,工作在復位從模式,被測信號接到其通道2的輸入腳。然后經內部邊沿檢測和內部濾波電路后,兵分兩路分別連接到IC1和IC2。顯然IC2使用直接輸入模式,IC1使用間接輸入模式,如下圖功能框圖示意。
但他發現被測信號頻率較高時,誤差就明顯變大了。當然,他也知道,任何測量肯定是有極限的。他現在就是想知道,能否基于現有方案將測量極限拉高點。比方說,他現在測量20KHz信號時就明顯誤差過大,導致測算結果難以采用。是否可以將可靠的測量結果提升到25KHz或更高呢。
我們不妨一起看看這個問題。依然保持相同的測量方案,TIM4工作在復位從模式,TIM3輸出的被測信號連接到TIM4的CH2,然后兵分兩路連接都TIM4的IC1與IC2。
顯然,我們先要確定測量的計時起點。可以采用IC2的上沿捕獲事件作為測量起點,即進入測試狀態。也可以基于上沿觸發信號產生定時器復位導致的更新事件加觸發事件作為測量起點,我在下面就是使用后者來進行測量并組織相應代碼。
IC1的下降沿觸發捕獲,捕獲到的計數器值存放于變量Value_1stCap【結合上圖來看】。
IC2的上升沿作為TIM4的觸發復位信號,且基于上升沿事件進行捕獲, 捕獲值存于Value_2ndCap。
從發生復位事件到發生第2次捕獲期間,對TIM4的更新事件次數進行統計,總的更新事件次數計為Total_Num_OvEvent。
從發生復位事件到發生第1次捕獲期間,對TIM4的更新事件次數進行統計后,計為Front_Num_OvEvent。
現在使用STM32CubeMx進行配置。重點關注TIM4的配置。TIM4的時基和捕獲配置參數如下:
結合上面配置我們不難看出,TIM4的溢出周期為20ms,TI2FP2作為TIM4的復位觸發信號,上沿觸發,同時IC2針對輸入信號的上沿進行捕獲。IC1針對輸入信號的下沿進行捕獲。
至于TIM3的配置沒啥特別的,就是產生PWM輸出信號,在代碼里將調整其PSC分頻系數和ARR參數以及CCR參數,以改變其頻率和占空比。選擇其通道1做PWM輸出。下面測試中,TIM3輸出的PWM波形的占空比固定為40%。
另外,STM32G4的系統主頻配置為170MHz,使用HSE 時鐘源。開啟TIM4的中斷響應使能。完成配置后創建工程。添加必要的用戶初始及啟動代碼。
__IO uint32_t Vaule_2ndCap = 0u; __IO uint32_t Vaule_1stCap = 0u; __IO float Signal_Cycle= 0.0f; __IO float Signal_Duty = 0.0f; __IO float Signal_Freq = 0.0f; __IO uint32_t Total_Num_OvEvent=0u; __IO uint32_t Front_Num_OvEvent=0u; __IO uint32_t Num_OvEvent =0u ; __IO uint32_t Measure_State = 0u; __IO uint32_t Clk_Internal; __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE); __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE); HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2); //enable IC1 interrupt of TIM4 HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1); //enable IC2 interrupt of TIM4 __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE); __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_TRIGGER);//enable Update interrupt of TIM4 Clk_Internal=HAL_RCC_GetHCLKFreq();//170MHzforG4Series Measure_State = 0x00; //initial state of Measuring Num_OvEvent = 0x00; //initial value of update count of TIM4 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
TIM4事件的所有中斷共用同一個中斷矢量入口。為了盡可能地測得較高的信號頻率,中斷處理代碼盡量要簡潔些,避免過多、過深的函數調用。
有關TIM4的捕獲中斷及更新中斷的處理代碼如下,包括IC1、IC2的捕獲中斷處理和更新中斷處理代碼,以及相關計算處理代碼。
void HAL_TIM4_PWM_Measure_IRQ(TIM_HandleTypeDef *htim) { if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER); if (Measure_State == 0) { Num_OvEvent = 0; // prepare count overflow events Measure_State = 0x01; //start measurement } } else { if(Measure_State != 0) { Num_OvEvent++; } } } /* Capture compare 1 event */ if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); if (Measure_State == 0x01) { Front_Num_OvEvent = Num_OvEvent; Measure_State =0x02; } } /* Capture compare 2 event */ if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2); if(Measure_State == 0x02) { Measure_State =0x03; Total_Num_OvEvent = Num_OvEvent; HAL_TIM4_IC_CaptureCallback(htim); //go to calculate pulse width and duty } } } void HAL_TIM4_IC_CaptureCallback(TIM_HandleTypeDef *htim) { /* Get the Input Capture value */ Vaule_1stCap = TIM4->CCR1;//HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); Vaule_2ndCap = TIM4->CCR2;//HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); Signal_Duty =(float)((Vaule_1stCap+(Front_Num_OvEvent*(TIM4_PERIOD+1)))*100u)/ (float)(Vaule_2ndCap+(Total_Num_OvEvent*(TIM4_PERIOD+1))); // Clk_Internal = HAL_RCC_GetHCLKFreq(); Signal_Freq =(float)(Clk_Internal/(TIM4_PSC+1))/(float)((Vaule_2ndCap+(Total_Num_OvEvent*(TIM4_PERIOD+1)))); Signal_Cycle = (float) (1.000f/Signal_Freq) ; Measure_State = 0x00; Num_OvEvent = 0x00; __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2); __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER); }
現在基于上面的配置及用戶代碼進行測量驗證。我們發現當TIM3輸出的待測信號頻率達到25KHz時,測得的頻率及占空比就發生了明顯的偏差。見下圖標注問號的第4欄信息。
即當被測頻率為25KHz,占空比為40%時,測得結果是下面的樣子,明顯偏差過大。
如果說被測信號頻率進一步提升的話,誤差會變得更大。那么,這種情形是否有改善機會呢?即在當前的測試方案下,可準確測量的被測信號頻率是否可以提高。
目前的中斷處理代碼應該說比較精簡,沒有什么可以優化的余地了。
聊到這里,有人可能發現了,我前面配置TIM4時,它是用來完成測量任務的,它的分頻系數PSC為169。即TIM4的計數器計數時鐘為1MHz,其計數分辨率為1us。不難理解,這個PSC系數應該會直接影響TIM4的計數精度,按理會影響到測量結果,尤其被測信號頻率較高時。
既然這樣,我們將TIM4的PSC系數改為0,并適當調整其ARR值再來實施測量,看看結果會怎么樣。見下圖,TIM3輸出的信號頻率仍然是占空比為40% 、頻率為25KHz的PWM信號。測量結果顯著地明顯改善,應該說此時結果是可以接受的,畢竟浮點運算也會帶來些偏差。
我們不妨在保持TIM3的PSC為0的條件下,將輸出頻率提升到50KHz、100KHz。繼續看看測量結果,見下圖:
從測試結果來看,當被測信號頻率提升到50KHz,測量結果仍然很好,完全可以采用。即使當被測信號頻率提升到100KHz時,測量結果雖發生了一些偏差,但此時的偏差相比PSC=169、被測信號為25KHz時的測試結果還要好得多。我把二者單列出來一起比較,見下圖:
經過上面的討論和驗證,我們知道,在使用TIMER做信號的頻率及占空比的測量時,當確定好測試方案后,為了盡可能地提升可以準確測試信號的頻率,一方面代碼要盡可能精簡、優化,另一方面,因測試TIMER的分頻系數會影響測試結果的精度及準確性,此時測試TIMER的分頻系數要盡可能設置小、或不做分頻,這點結合具體應用場景來定。
關于上面的的話題,其實還可以有很多繼續延伸的空間,因時間和篇幅問題,就先聊到這里。有興趣的話,可以基于上面配置和分享的參考源碼做些快速測試驗證,也歡迎進一步地討論交流。
審核編輯:湯梓紅
-
mcu
+關注
關注
146文章
17148瀏覽量
351213 -
占空比
+關注
關注
0文章
109瀏覽量
29090 -
定時器
+關注
關注
23文章
3248瀏覽量
114816 -
Timer
+關注
關注
1文章
64瀏覽量
12788
原文標題:利用TIMER測量信號周期及占空比的精度話題
文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論