有人使用STM32G4系列的通用型TIMER基于捕獲功能對外來信號進(jìn)行周期及占空比的測量。他用TIM3產(chǎn)生頻率、占空比可調(diào)的PWM輸出做為被測信號。TIM4用來進(jìn)行頻率測量,工作在復(fù)位從模式,被測信號接到其通道2的輸入腳。然后經(jīng)內(nèi)部邊沿檢測和內(nèi)部濾波電路后,兵分兩路分別連接到IC1和IC2。顯然IC2使用直接輸入模式,IC1使用間接輸入模式,如下圖功能框圖示意。
但他發(fā)現(xiàn)被測信號頻率較高時,誤差就明顯變大了。當(dāng)然,他也知道,任何測量肯定是有極限的。他現(xiàn)在就是想知道,能否基于現(xiàn)有方案將測量極限拉高點。比方說,他現(xiàn)在測量20KHz信號時就明顯誤差過大,導(dǎo)致測算結(jié)果難以采用。是否可以將可靠的測量結(jié)果提升到25KHz或更高呢。
我們不妨一起看看這個問題。依然保持相同的測量方案,TIM4工作在復(fù)位從模式,TIM3輸出的被測信號連接到TIM4的CH2,然后兵分兩路連接都TIM4的IC1與IC2。
顯然,我們先要確定測量的計時起點??梢圆捎肐C2的上沿捕獲事件作為測量起點,即進(jìn)入測試狀態(tài)。也可以基于上沿觸發(fā)信號產(chǎn)生定時器復(fù)位導(dǎo)致的更新事件加觸發(fā)事件作為測量起點,我在下面就是使用后者來進(jìn)行測量并組織相應(yīng)代碼。
IC1的下降沿觸發(fā)捕獲,捕獲到的計數(shù)器值存放于變量Value_1stCap【結(jié)合上圖來看】。
IC2的上升沿作為TIM4的觸發(fā)復(fù)位信號,且基于上升沿事件進(jìn)行捕獲, 捕獲值存于Value_2ndCap。
從發(fā)生復(fù)位事件到發(fā)生第2次捕獲期間,對TIM4的更新事件次數(shù)進(jìn)行統(tǒng)計,總的更新事件次數(shù)計為Total_Num_OvEvent。
從發(fā)生復(fù)位事件到發(fā)生第1次捕獲期間,對TIM4的更新事件次數(shù)進(jìn)行統(tǒng)計后,計為Front_Num_OvEvent。
現(xiàn)在使用STM32CubeMx進(jìn)行配置。重點關(guān)注TIM4的配置。TIM4的時基和捕獲配置參數(shù)如下:
結(jié)合上面配置我們不難看出,TIM4的溢出周期為20ms,TI2FP2作為TIM4的復(fù)位觸發(fā)信號,上沿觸發(fā),同時IC2針對輸入信號的上沿進(jìn)行捕獲。IC1針對輸入信號的下沿進(jìn)行捕獲。
至于TIM3的配置沒啥特別的,就是產(chǎn)生PWM輸出信號,在代碼里將調(diào)整其PSC分頻系數(shù)和ARR參數(shù)以及CCR參數(shù),以改變其頻率和占空比。選擇其通道1做PWM輸出。下面測試中,TIM3輸出的PWM波形的占空比固定為40%。
另外,STM32G4的系統(tǒng)主頻配置為170MHz,使用HSE 時鐘源。開啟TIM4的中斷響應(yīng)使能。完成配置后創(chuàng)建工程。添加必要的用戶初始及啟動代碼。
__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事件的所有中斷共用同一個中斷矢量入口。為了盡可能地測得較高的信號頻率,中斷處理代碼盡量要簡潔些,避免過多、過深的函數(shù)調(diào)用。
有關(guān)TIM4的捕獲中斷及更新中斷的處理代碼如下,包括IC1、IC2的捕獲中斷處理和更新中斷處理代碼,以及相關(guān)計算處理代碼。
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); }
現(xiàn)在基于上面的配置及用戶代碼進(jìn)行測量驗證。我們發(fā)現(xiàn)當(dāng)TIM3輸出的待測信號頻率達(dá)到25KHz時,測得的頻率及占空比就發(fā)生了明顯的偏差。見下圖標(biāo)注問號的第4欄信息。
即當(dāng)被測頻率為25KHz,占空比為40%時,測得結(jié)果是下面的樣子,明顯偏差過大。
如果說被測信號頻率進(jìn)一步提升的話,誤差會變得更大。那么,這種情形是否有改善機(jī)會呢?即在當(dāng)前的測試方案下,可準(zhǔn)確測量的被測信號頻率是否可以提高。
目前的中斷處理代碼應(yīng)該說比較精簡,沒有什么可以優(yōu)化的余地了。
聊到這里,有人可能發(fā)現(xiàn)了,我前面配置TIM4時,它是用來完成測量任務(wù)的,它的分頻系數(shù)PSC為169。即TIM4的計數(shù)器計數(shù)時鐘為1MHz,其計數(shù)分辨率為1us。不難理解,這個PSC系數(shù)應(yīng)該會直接影響TIM4的計數(shù)精度,按理會影響到測量結(jié)果,尤其被測信號頻率較高時。
既然這樣,我們將TIM4的PSC系數(shù)改為0,并適當(dāng)調(diào)整其ARR值再來實施測量,看看結(jié)果會怎么樣。見下圖,TIM3輸出的信號頻率仍然是占空比為40% 、頻率為25KHz的PWM信號。測量結(jié)果顯著地明顯改善,應(yīng)該說此時結(jié)果是可以接受的,畢竟浮點運(yùn)算也會帶來些偏差。
我們不妨在保持TIM3的PSC為0的條件下,將輸出頻率提升到50KHz、100KHz。繼續(xù)看看測量結(jié)果,見下圖:
從測試結(jié)果來看,當(dāng)被測信號頻率提升到50KHz,測量結(jié)果仍然很好,完全可以采用。即使當(dāng)被測信號頻率提升到100KHz時,測量結(jié)果雖發(fā)生了一些偏差,但此時的偏差相比PSC=169、被測信號為25KHz時的測試結(jié)果還要好得多。我把二者單列出來一起比較,見下圖:
經(jīng)過上面的討論和驗證,我們知道,在使用TIMER做信號的頻率及占空比的測量時,當(dāng)確定好測試方案后,為了盡可能地提升可以準(zhǔn)確測試信號的頻率,一方面代碼要盡可能精簡、優(yōu)化,另一方面,因測試TIMER的分頻系數(shù)會影響測試結(jié)果的精度及準(zhǔn)確性,此時測試TIMER的分頻系數(shù)要盡可能設(shè)置小、或不做分頻,這點結(jié)合具體應(yīng)用場景來定。
關(guān)于上面的的話題,其實還可以有很多繼續(xù)延伸的空間,因時間和篇幅問題,就先聊到這里。有興趣的話,可以基于上面配置和分享的參考源碼做些快速測試驗證,也歡迎進(jìn)一步地討論交流。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17984瀏覽量
367097 -
占空比
+關(guān)注
關(guān)注
0文章
112瀏覽量
29572 -
定時器
+關(guān)注
關(guān)注
23文章
3298瀏覽量
118975 -
Timer
+關(guān)注
關(guān)注
1文章
64瀏覽量
13218
原文標(biāo)題:利用TIMER測量信號周期及占空比的精度話題
文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
怎么設(shè)置TIMER周期
如何利用LabVIEW測量一個心電信號的周期?
求有償求購周期方波信號頻率周期測量設(shè)計
測量方波周期以及占空比的方法是什么
如何測量PWM信號的占空比和周期?
如何采用MSP430單片機(jī)實現(xiàn)PWM信號
測量方波周期以及占空比的兩種方法介紹

評論