有人使用STM32H7系列芯片開發(fā)產(chǎn)品,其中用到TIM1/TIM8兩個定時器做PWM輸出,并且TIM1/TIM8建立起主從關(guān)系同時啟動,使用完全相同的時間參數(shù)和PWM配置,各自輸出3路同頻同相的PWM驅(qū)動信號。不過,在使用過程中,可能時不時地需要暫停兩個定時器的輸出,等到適當(dāng)時機(jī)再啟動全部通道PWM輸出。可他發(fā)現(xiàn),2個定時器的PWM輸出剛開始還同步得好好的,但隨著程序的運行,一段時間后,來自兩個定時器的PWM輸出明顯不再同步了,而是出現(xiàn)了相移。
我這里各選TIM1/TIM8的CH1來做說明。比方說,程序剛開始運行時,來自2個定時器的2個通道PWM輸出是完全同步的,如下圖所示:
LATER……
經(jīng)過一段時間后,2個定時器的PWM輸出變得有相差了,就像下面的樣子,兩個定時器的PWM輸出相差隨著程序的運行還在不停變化,輸出不再有同步可言。
經(jīng)過測試發(fā)現(xiàn),如果沒有中途時不時的通道啟、停動作,2個定時器的PWM輸出倒是一直同步得很好。也就是說,中途不時地對輸出通道的啟、停導(dǎo)致了PWM輸出的相移。
查看了他的相關(guān)操作代碼,大致是這樣操作的。【下面是我參考客戶寫法重寫的驗證代碼。TIM8是MASTER,TIM1是SLAVE。功能簡單、清晰,就是讓來自TIM1和TIM8的2個通道先運行一會,然后暫停一會,這樣循環(huán)。下面代碼重點看while(1)循環(huán)體。】
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //Start PWM of TIM1_CH1 HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1); //Start PWM of TIM8_CH1 。。。。。。 while (1) { HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);//Stop PWM of TIM1_CH1 HAL_TIM_PWM_Stop(&htim8, TIM_CHANNEL_1);//Stop PWM of TIM8_CH1 HAL_Delay(2000); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //Start PWM of TIM1_CH1 HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1); //Start PWM of TIM8_CH1 HAL_Delay(2000); }
使用上面測試代碼運行一陣子后,本來同步得很好的2路PWM波形就漸漸產(chǎn)生相移了。
這里調(diào)用的HAL_TIM_PWM_Stop()函數(shù)來關(guān)閉指定通道的PWM輸出,是有效的。不過,當(dāng)我們點進(jìn)該函數(shù)里面去閱讀時,該函數(shù)不僅關(guān)閉了相應(yīng)通道的輸出功能,連計數(shù)器也關(guān)閉了。下面截圖是該函數(shù)的內(nèi)容,其中箭頭所指是關(guān)閉定時器的計數(shù)器的代碼。
根據(jù)客戶的需求,每次關(guān)閉通道輸出只是臨時性的,每次一同把計數(shù)器也關(guān)斷似乎太過了,不是很合適的做法,明顯不必要。那么,如果我們把這個函數(shù)換成只針對定時器通道的輸出功能做關(guān)閉、開啟的函數(shù)會怎么樣呢?
在HAL庫里,有個函數(shù)就是實現(xiàn)此功能的:
//關(guān)閉通道輸出功能
TIM_CCxChannelCmd(TIMx, TIM_CHANNEL_1, TIM_CCx_DISABLE);
//啟用通道輸出功能
TIM_CCxChannelCmd(TIMx, TIM_CHANNEL_1, TIM_CCx_ENABLE);
我們把前面的測試代碼改換成下面的寫法再來驗證。
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //Start PWM of TIM1_CH1 HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1); //Start PWM of TIM8_CH1 。。。。。。 while (1) { TIM_CCxChannelCmd(htim1.Instance,TIM_CHANNEL_1,TIM_CCx_DISABLE);//關(guān)閉輸出 TIM_CCxChannelCmd(htim8.Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); //關(guān)閉輸出 HAL_Delay(2000); TIM_CCxChannelCmd(htim1.Instance,TIM_CHANNEL_1,TIM_CCx_ENABLE);//啟用輸出 TIM_CCxChannelCmd(htim8.Instance,TIM_CHANNEL_1,TIM_CCx_ENABLE);//啟用輸出 HAL_Delay(2000); }
針對修改過的測試代碼進(jìn)行驗證,結(jié)果發(fā)現(xiàn)來自2個定時器的PWM輸出同步得很好很穩(wěn)定,不飄不移了。
第2種新寫法跟原寫法的最大差別就在于-----新寫法的代碼里對通道輸出做啟停操作時完全不涉及計數(shù)器的開、關(guān), 2個TIMER的計數(shù)器自始至終就不曾受到其它干預(yù)而影響正常計數(shù),一直在持續(xù)地、按部就班地、周期性地計數(shù),因為完全相同的時間參數(shù),所以2個計數(shù)器的計數(shù)也保持著很好的同步。
現(xiàn)在的問題是,為何第一種寫法會讓2個定時器的PWM輸出產(chǎn)生相移呢?
原因就出在使用HAL_TIM_PWM_Stop()函數(shù)來關(guān)閉通道輸出這個做法上,這里調(diào)用它來實現(xiàn)通道的關(guān)閉不合理。前面我們分析了,該函數(shù)不僅關(guān)閉通道輸出,而且還停止了相應(yīng)計數(shù)器。我們看看其中的兩行關(guān)閉通道PWM輸出的代碼:
在程序里面,一前一后,即先停止TIM1的計數(shù)器,然后才停止TIM8的計數(shù)器。顯然,因為這個先后關(guān)系,導(dǎo)致TIM8停止時總要比TIM1多計些數(shù)。這里我們簡單點以便于溝通,假設(shè)TIM8停止計數(shù)時比TIM1多計2個數(shù)。也就是說每次對2個通道做關(guān)閉操作時,同時對2個計數(shù)器也做一次停止操作,每次對定時器的停止操作使得TIM8比TIM1多計2個數(shù)。隨著這種操作次數(shù)的增加,每次重新啟動2個定時器時,2個計數(shù)器的起點值的差距也在增加【當(dāng)然,這個差距變化可能會有周期性】,最終導(dǎo)致2個定時器的PWM輸出產(chǎn)生了相移,而且相移還在不斷變化。
關(guān)于頻繁啟停通道導(dǎo)致2個計數(shù)器每次停止后再次啟動時的計數(shù)器起始值的差值總在變化的結(jié)論,我換個比較通俗形象的類比說法來解釋。
假設(shè)有2個運動員A和B,下圖中的紅星和綠星分別代表這兩個運動員。他倆經(jīng)常一起繞圈跑步訓(xùn)練,跑步速度一樣。我們現(xiàn)在模擬2個場景。
第一個場景,就是他倆一起從某點開始跑步,要跑就一起跑,要停就一起停。顯然,這樣的話,任何時候他倆都是在一起,物理上來看二人相對靜止。此場景對應(yīng)下圖中的左邊圓圈情形。
第二個場景,還是他倆一起繞圈跑步,跑步速度始終一樣,不過這時旁邊多了個教練。當(dāng)他倆從某點開始跑起來后,若要停下歇息需得到教練指令。這個教練有個習(xí)慣,每次都是先叫A停下,然后才叫B停下歇息,導(dǎo)致每次2個人停下歇息時,B總要比A多跑兩步,但二人每次重新起跑時又是同時的。就這樣持續(xù),不難想象二人之間的距離總是在變化,再也看不到場景1情形下的相對靜止了。這兩個運動員在跑道上的間距變化就像基于第一種代碼寫法下的2個計數(shù)器值的差值變動。見下圖的右邊圓圈紅星與綠星的間距變化。這里只畫一圈示意下。
我們知道,這里定時器的PWM輸出是根據(jù)TIMER比較器的值與計數(shù)器值的比較結(jié)果而決定其輸出電平。盡管2個定時器的基本配置參數(shù)都一樣,但由于頻繁啟停計數(shù)器,導(dǎo)致每次啟動時計數(shù)初始值都在變化,進(jìn)而導(dǎo)致PWM波形輸出不再保持同步。
這樣說可能有點抽象,我們不妨結(jié)合下面圖形看看會直觀點。下圖帶箭頭斜線示意計數(shù)方向、計數(shù)起點、終點。紅色虛線表示2個定時器CH1設(shè)置的CCR值的水平。
基于客戶原寫法代碼,假設(shè)經(jīng)過多次針對通道的啟、停操作后的某個時刻【Tx】重新啟動2個定時器及PWM輸出,A,B兩點表示TIM1和TIM8計數(shù)器在Tx時刻的起始值,其它配置參數(shù)都一樣。下面是基于應(yīng)用當(dāng)前場景,分別來自TIM1/TIM8的2路PWM輸出波形示意圖。【這里假定TIM1和TIM8的使用相同配置,且當(dāng)CCR>CNT時輸出高,否則輸出低】
因2個定時器采用完全相同的配置,所以2路PWM波形特征是一樣的。但由于啟動時刻2個定時器的計數(shù)初值不一樣,輸出的波形卻有了相差,如上圖所示。
這里或許有人會問,原始寫法里調(diào)用HAL_TIM_PWM_Start();是不是也不太合理呢?談不上不合理,但用得不太合適,從功能實現(xiàn)上看不夠簡潔、利落。這里TIM1/TIM8基于觸發(fā)啟動的主從關(guān)系,作為主定時器的TIM8的啟動放在TIM1的后面就可以了,TIM8啟動的同時啟動從TIM1。
結(jié)合這里的應(yīng)用,改過寫的第2種代碼比較清爽簡潔。那么,順便問一句,可否在原寫法的代碼基礎(chǔ)上不做大的改寫,只做局部微調(diào)來解決問題呢?答案是肯定的,我也做過較長時間的驗證測試。有興趣的話可以自行研究下,其實前面文字里也隱含了答案。
審核編輯:湯梓紅
-
PWM
+關(guān)注
關(guān)注
114文章
5193瀏覽量
214310 -
信號
+關(guān)注
關(guān)注
11文章
2797瀏覽量
76923 -
定時器
+關(guān)注
關(guān)注
23文章
3253瀏覽量
115057 -
代碼
+關(guān)注
關(guān)注
30文章
4805瀏覽量
68778 -
stm32h7
+關(guān)注
關(guān)注
0文章
37瀏覽量
1753
原文標(biāo)題:本來同步的信號為何有相差了?
文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論