有人使用STM32F4系列開發產品,程序運行過程中需要不時地對外輸出一串驅動脈沖,并要求這幾串脈沖的頻率可變、占空比固定。他想到使用基于STM32定時器的DMA
BURST傳輸。具體點說,他期望不時地通過TIM3的CH1輸出一串頻率可變、占空比固定的脈沖然后停下來。這個思路在原理上是沒問題的,可是他在測試過程中發現怎么也折騰不出預期的效果。
他目前使用的芯片是STM32F401,雖有點老舊,但我查看了手冊,確認該芯片的TIM3是支持基于TIMER事件實現TIME寄存器與內存間的DMABURST傳輸的。即每個TIMER事件可以申請多個DMA請求從而實現定時器寄存器與內存間的批量數據傳輸。要知某個STM32
TIMER是否支持上述功能,只需查看STM32參考手冊的相關定時器的寄存器中有無TIMx_DCR和TIMx_DMAR寄存器的介紹。
既然支持,為什么實現不了呢?關于這個功能我們還需要注意幾點:
1、所選擇的TIMER必須支持基于定時器事件的DMA BURST傳輸功能。
2、觸發事件必須是來自參與DMA傳輸的定時器事件,不能是別的定時器事件。比方說你想實現TIM1的寄存器與內存間的DMA
BURST傳輸,觸發事件不能是來自TIM2、TIM3這些非TIM1的事件。
3、定時器DMA
Burst傳輸時,用來被BURST訪問的定時器寄存器應該是同一定時器的而且是地址連續的寄存器,不可跳躍訪問。比方說像下面某TIMER的4個比較寄存器物理地址是安排在一起的,而CH2恰好因為某些原因沒有被用上。
如果你僅對CH1/CH3/CH4三個通道的比較寄存器的值做BURST訪問,此時盡管CH2沒有被用上,BURST訪問的傳輸個數應該是4而不是3。
4、STM32
HAL庫里的例程或函數重點在演示相應的功能或特性,但它不能包羅萬象或保證適用于任何場景。有些時候我們可能需要在現有庫函數的前提下適當地做些調整來滿足需求。
結合這幾點,我們一起排查下。第1點、第2點已經核對過了,沒問題??纯吹?點,即設置BURST傳輸個數。下圖是F40x系列TIM2~TIM5的內存地址映射圖。
現在使用者真正需要用到的寄存器只有TIM3-》ARR和TIM3-》CCR1兩個寄存器,但二者中間還有個預留空位【其它高級定時器的RCR寄存器的位置】也必須算進來,即這里BURST傳輸個數應該是3而不是2。
再看看上面提到的第4點要注意的地方。這點我就不過多解釋了,ST提供的HAL庫例程及相關函數只能實現1次BURST傳輸的功能,如果要實現多次BURST傳輸就得在其代碼基礎上做些調整,更多細節可以參考我之前分享的那篇《STM32定時器BURST傳輸介紹及示例》。不過,在那篇的演示例程里我使用的是DMA
Circular模式,現在的用戶則要使用DMA
Normal模式。采用Normal模式和采用Circular模式基于現有HAL庫函數組織代碼還略有差異,若沒處理好這點小差異,可能讓你完全出不來想要的結果。
下面我使用STM32G4芯片的TIM3-CH1演示上面用戶的功能。每次輸出5個脈沖,3次輸出為一個循環,同一循環中的3次輸出的頻率各不相同,占空比一樣。【為什么沒用STM32F401芯片,是因為此時手上沒有帶該芯片的開發板。不過演示功能的配置及代碼基本一樣?!?/p>
我使用CubeMx對TIM3進行配置,參考配置如下:
開啟TIM3基于更新事件的DMA傳輸功能并做相關配置。
配置完成,生成初始化工程,添加用戶代碼。
我準備了3串脈沖的ARR/CCR1的值,分別以數組PulseData1[]、PulseData2[]、PulseData3[]來存放,占空比都設置為50%。顯然數組行中間的0值用于前面提到過的預留字,此處無實際作用。另外,每個數組中的第6行數據其實是關閉當前通道PWM輸出,具體應用時注意結合所選擇的PWM模式及極性選擇。
-
STM32
+關注
關注
2270文章
10915瀏覽量
356741 -
控制
+關注
關注
4文章
1013瀏覽量
122703
發布評論請先 登錄
相關推薦
評論