【STM32H7教程】第39章 STM32H7的DMAMUX基礎知識(重要)

  • 2020 年 1 月 13 日
  • 筆記

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第39章       STM32H7的DMAMUX基礎知識(重要)

本章教程為大家講解DMAMUX(Direct memory access request multiplexer,直接存儲器訪問請求復用器),本章知識點非常重要,是掌握好DMA1,DMA2和BDMA的關鍵一步。

39.1 初學者重要提示

39.2 DMAMUX基礎知識

39.3 DMAMUX的HAL庫用法

39.4 源文件stm32h7xx_hal_dma_ex.c

39.5 總結

39.1 初學者重要提示

  •   DMAMUX其實就是DMA控制器前一級的多路選擇器,有了這個選擇器就不用再像F1,F4系列那樣每個通道(數據流)要固定選擇指定的外設,有了多路選擇器就可以任意選擇,外設使用DMA方式時無需再選擇指定的DMA通道(數據流),任意通道(數據流)都可以。

39.2 DMAMUX基礎知識

當前STM32H7有兩路DMAMUX,分別是DMAMUX1和DMAMUX2,其中DMAMUX1負責DMA1和DMA2,而DMAMUX2負責BDMA。

39.2.1 DMAMUX和DMA的連接關係

認識一個外設,最好的方式就是看它的框圖,方便我們快速的了解DMAMUX的基本功能,然後再看手冊了解細節。首先來看下DMAMUX與DMA之間的連接方式,從整體上把握下,可以更好的理解DMAMUX的作用。

DMAMUX1有16個輸出通道,前8個通道分別連接DMA1 Stream0到Stream7,而後8個通道分別連接DMA2 Stream0到Stream7。上面DMAMUX1的前8路接到DMA1的8路數據流通道Stream0到Stream7中。

DMAMUX2有8個輸出通道,連接BDMA的8個輸入通道:

39.2.2 DMAMUX的硬體框圖

這個框圖對於理解DMAMUX至關重要。

通過這個框圖,我們可以得到如下資訊:

  •   DMA requests from peripherals介面

對於DMAMUX1來說,這個介面支援107個DMA外設請求,供DMA1和DMA2的數據流使用:

#define DMA_REQUEST_ADC1             9U  /*!< DMAMUX1 ADC1 request */  #define DMA_REQUEST_ADC2             10U /*!< DMAMUX1 ADC2 request */    #define DMA_REQUEST_TIM1_CH1         11U  /*!< DMAMUX1 TIM1 CH1 request  */  #define DMA_REQUEST_TIM1_CH2         12U  /*!< DMAMUX1 TIM1 CH2 request  */  #define DMA_REQUEST_TIM1_CH3         13U  /*!< DMAMUX1 TIM1 CH3 request  */  #define DMA_REQUEST_TIM1_CH4         14U  /*!< DMAMUX1 TIM1 CH4 request  */  #define DMA_REQUEST_TIM1_UP          15U  /*!< DMAMUX1 TIM1 UP request   */  #define DMA_REQUEST_TIM1_TRIG        16U  /*!< DMAMUX1 TIM1 TRIG request */  #define DMA_REQUEST_TIM1_COM         17U  /*!< DMAMUX1 TIM1 COM request  */    中間部分省略未寫    #define DMA_REQUEST_TIM16_CH1       109U  /*!< DMAMUX1 TIM16 CH1 request  */  #define DMA_REQUEST_TIM16_UP        110U  /*!< DMAMUX1 TIM16 UP request   */    #define DMA_REQUEST_TIM17_CH1       111U  /*!< DMAMUX1 TIM17 CH1 request  */  #define DMA_REQUEST_TIM17_UP        112U  /*!< DMAMUX1 TIM17 UP request   */    #define DMA_REQUEST_SAI3_A          113U  /*!< DMAMUX1 SAI3 A request  */  #define DMA_REQUEST_SAI3_B          114U  /*!< DMAMUX1 SAI3 B request  */    #define DMA_REQUEST_ADC3            115U  /*!< DMAMUX1 ADC3  request  */

對於DMAMUX2來說,這個介面支援9個DMA外設請求,供BDMA通道使用:

#define BDMA_REQUEST_LPUART1_RX       9U  /*!< DMAMUX2 LP_UART1_RX request */  #define BDMA_REQUEST_LPUART1_TX      10U  /*!< DMAMUX2 LP_UART1_TX request */  #define BDMA_REQUEST_SPI6_RX         11U  /*!< DMAMUX2 SPI6 RX request     */  #define BDMA_REQUEST_SPI6_TX         12U  /*!< DMAMUX2 SPI6 TX request     */  #define BDMA_REQUEST_I2C4_RX         13U  /*!< DMAMUX2 I2C4 RX request     */  #define BDMA_REQUEST_I2C4_TX         14U  /*!< DMAMUX2 I2C4 TX request     */  #define BDMA_REQUEST_SAI4_A          15U  /*!< DMAMUX2 SAI4 A request      */  #define BDMA_REQUEST_SAI4_B          16U  /*!< DMAMUX2 SAI4 B request      */  #define BDMA_REQUEST_ADC3            17U  /*!< DMAMUX2 ADC3 request        */

這裡特別注意一點,DMA1,DMA2和BDMA都支援存儲區到存儲區的傳輸。

  •   Trigger inputs介面

除了正常的DMA請求可以輸入到DMAMUX裡面,通過設置觸發條件也可以生成DMA觸發請求。這樣就比較靈活了,不支援DMA的外設也可以通過Trigger inputs介面觸發DMA傳輸,比如我們可以將RAM中的數據通過定時器觸發直接輸出到GPIO,這樣就可以產生各種脈衝效果。

DMAMUX1支援8種觸發輸入,供DMA1和DMA2使用:

#define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT   0U  #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT   1U  #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT   2U  #define HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT        3U  #define HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT        4U  #define HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT        5U  #define HAL_DMAMUX1_REQ_GEN_EXTI0             6U  #define HAL_DMAMUX1_REQ_GEN_TIM12_TRGO        7U  

DMAMUX2支援的30種觸發輸入,供BDMA使用:

#define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT   0U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT   1U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT   2U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT   3U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT   4U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT   5U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT   6U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP   7U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP   8U  #define HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP       9U  #define HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT       10U  #define HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP      11U  #define HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT       12U  #define HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP      13U  #define HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP      14U  #define HAL_DMAMUX2_REQ_GEN_I2C4_WKUP        15U  #define HAL_DMAMUX2_REQ_GEN_SPI6_WKUP        16U  #define HAL_DMAMUX2_REQ_GEN_COMP1_OUT        17U  #define HAL_DMAMUX2_REQ_GEN_COMP2_OUT        18U  #define HAL_DMAMUX2_REQ_GEN_RTC_WKUP         19U  #define HAL_DMAMUX2_REQ_GEN_EXTI0            20U  #define HAL_DMAMUX2_REQ_GEN_EXTI2            21U  #define HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT      22U  #define HAL_DMAMUX2_REQ_GEN_SPI6_IT          23U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT    24U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT    25U  #define HAL_DMAMUX2_REQ_GEN_ADC3_IT          26U  #define HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT    27U  #define HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT      28U  #define HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT      29U   
  •   Interrupt介面

用於觸發中斷。                                                                                                                             

  •   Synchronization inputs介面

同步輸入介面可以用來控制DMAMUX的輸入端的DMA外設請求到輸出端的同步控制,其實就是控制何時輸出。

DMAMUX1支援的8種同步輸入,供DMA1和DMA2使用:

#define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT   0U  #define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT   1U  #define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT   2U  #define HAL_DMAMUX1_SYNC_LPTIM1_OUT        3U  #define HAL_DMAMUX1_SYNC_LPTIM2_OUT        4U  #define HAL_DMAMUX1_SYNC_LPTIM3_OUT        5U  #define HAL_DMAMUX1_SYNC_EXTI0             6U  #define HAL_DMAMUX1_SYNC_TIM12_TRGO        7U   

DMAMUX2支援的16種同步輸入,供BDMA使用:

#define HAL_DMAMUX2_SYNC_DMAMUX2_CH0_EVT   0U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH1_EVT   1U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH2_EVT   2U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH3_EVT   3U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH4_EVT   4U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH5_EVT   5U  #define HAL_DMAMUX2_SYNC_LPUART1_RX_WKUP   6U  #define HAL_DMAMUX2_SYNC_LPUART1_TX_WKUP   7U  #define HAL_DMAMUX2_SYNC_LPTIM2_OUT        8U  #define HAL_DMAMUX2_SYNC_LPTIM3_OUT        9U  #define HAL_DMAMUX2_SYNC_I2C4_WKUP        10U  #define HAL_DMAMUX2_SYNC_SPI6_WKUP        11U  #define HAL_DMAMUX2_SYNC_COMP1_OUT        12U  #define HAL_DMAMUX2_SYNC_RTC_WKUP         13U  #define HAL_DMAMUX2_SYNC_EXTI0            14U  #define HAL_DMAMUX2_SYNC_EXTI2            15U  
  •   DMA Channels event介面

DMAMUX的事件輸出。

  •   DMA requests to DMA controllers介面

DMAMUX的輸出,發往DMA1,DMA2或者BDMA。

39.2.3 請求發生器(Request Generator)

請求觸發器最大的優勢就是可以讓不支援DMA傳輸的外設也可以通過Trigger inputs介面觸發DMA傳輸,比如我們可以將RAM中的數據通過定時器觸發直接輸出到GPIO,這樣就可以產生各種脈衝效果,這樣就比較靈活了。

這裡我們再進一步的認識下請求發生器,通過下面框圖可以看出請求發生器有n個通道,並且每個通道都支援t個觸發。這裡有一個關鍵知識點,所有這些通道可以選擇同一個觸發源。

了解了這些之後,我們要對它的工作過程有一個簡單的認識,看下面的時序圖:

  •   dmamux_req_gen訊號請求發生器生成的DMA請求。
  •   dmamux_req_out訊號是DMAMUX的輸出,供DMA1,DMA2或者BDMA使用。
  • Request generator counter這個計數器比較重要,它的意思是一次dmamux_trg觸發訊號,可以連續執行的DMA請求,最大32次。這裡是以DMA可以執行的最快速度進行響應的。每執行一次,計數器減1,減到0後自動載入用戶設置的最大次數,等待下次觸發,依次進行。如果計數器還沒有減到0就再次觸發,請求發生器的中斷狀態暫存器DMAMUX_RGSR的標誌將被置位,如果使能了中斷,將會被觸發。
  •   dmamux_trg訊號是觸發源。

39.2.4 同步觸發和請求復用器(Request multiplexer)

同步輸入介面可以用來控制DMAMUX的輸入端的DMA外設請求到輸出端的同步控制,其實就是控制何時輸出。

這裡我們再進一步的認識下請求復用器,從下面的框圖中可以看出請求發生器有m個通道,並且每個通道都支援n+p+2個DMA請求,但是每個通道不可以選擇相同的DMA請求。

特別注意紅色方框的地方,請求發生器的n個DMA請求和p個DMA外設請求全都彙集於此,可供這裡的多路選擇器選擇。

了解了這些之後,我們要對它的工作過程有一個簡單的認識,看下面的時序圖:

下面連續同步三次的效果,每次產生4次DMA請求:

  •   dmamux_reqx訊號是請求復用器的輸入端。
  •   dmamux_syncx是同步觸發訊號。
  •   dmamux_req_outx訊號是DMAMUX的輸出,供DMA1,DMA2或者BDMA使用。
  • DMA request counter這個計數器比較重要,他的意思是一次dmamux_syncx觸發訊號,可以連續執行的DMA請求,最大32次。這裡是以DMA請求可以執行的最快速度進行響應的。每執行一次,計數器減1,減到0後自動載入用戶設置的最大次數,等待下次觸發,依次進行。如果計數器還沒有減到0就再次觸發,請求發生器的中斷狀態暫存器DMAMUX_CSR的標誌將被置位,如果使能了中斷,將會被觸發。
  •   dmamux_evt訊號是輸出事件。

39.2.5 正常的DMA請求方式

除了前面說的請求發生器產生的DMA請求和同步觸發產生的DMA請求,關閉了這兩種方式後也可以通過DMAMUX正常發出DMA請求的,這種情況和之前使用F1和F4系列是一樣的。

39.3 DMAMUX的HAL庫用法

DMAMUX的HAL庫用法其實就是幾個結構體變數成員的配置和使用,然後配置GPIO、時鐘,並根據需要配置NVIC、中斷和DMA。下面我們逐一展開為大家做個說明。

39.3.1 請求發生器結構體HAL_DMA_MuxRequestGeneratorConfigTypeDef

HAL_DMA_MuxRequestGeneratorConfigTypeDef的定義如下:

typedef struct  {   uint32_t SignalID;  /*!< Specifies the ID of the signal used for DMAMUX request generator                           This parameter can be a value of @ref DMAEx_MUX_SignalGeneratorID_selection */      uint32_t Polarity; /*!< Specifies the polarity of the signal on which the request is generated.                        This parameter can be a value of @ref DMAEx_MUX_RequestGeneneratorPolarity_selection */      uint32_t RequestNumber;  /*!< Specifies the number of DMA request that will be generated after a signal event.                             This parameters can be in the range 1 to 32 */    }HAL_DMA_MuxRequestGeneratorConfigTypeDef;

下面將這三個結構體成員一 一為大家做個說明。

  • SingnalID

請求發生器的觸發源ID選擇,DMAMUX1可以選擇的觸發源ID如下:

#define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT   0U  #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT   1U  #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT   2U  #define HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT        3U  #define HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT        4U  #define HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT        5U  #define HAL_DMAMUX1_REQ_GEN_EXTI0             6U  #define HAL_DMAMUX1_REQ_GEN_TIM12_TRGO        7U  

DMAMUX2可以選擇的觸發源ID如下:

#define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT   0U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT   1U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT   2U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT   3U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT   4U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT   5U  #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT   6U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP   7U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP   8U  #define HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP       9U  #define HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT       10U  #define HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP      11U  #define HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT       12U  #define HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP      13U  #define HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP      14U  #define HAL_DMAMUX2_REQ_GEN_I2C4_WKUP        15U  #define HAL_DMAMUX2_REQ_GEN_SPI6_WKUP        16U  #define HAL_DMAMUX2_REQ_GEN_COMP1_OUT        17U  #define HAL_DMAMUX2_REQ_GEN_COMP2_OUT        18U  #define HAL_DMAMUX2_REQ_GEN_RTC_WKUP         19U  #define HAL_DMAMUX2_REQ_GEN_EXTI0            20U  #define HAL_DMAMUX2_REQ_GEN_EXTI2            21U  #define HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT      22U  #define HAL_DMAMUX2_REQ_GEN_SPI6_IT          23U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT    24U  #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT    25U  #define HAL_DMAMUX2_REQ_GEN_ADC3_IT          26U  #define HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT    27U  #define HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT      28U  #define HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT      29U   
  • Polarity

觸發訊號的極性設置,可以是上升沿觸發、下降沿觸發或者雙沿觸發。

#define HAL_DMAMUX_REQ_GEN_NO_EVENT        0x00000000U  #define HAL_DMAMUX_REQ_GEN_RISING          DMAMUX_RGxCR_GPOL_0  #define HAL_DMAMUX_REQ_GEN_FALLING         DMAMUX_RGxCR_GPOL_1  #define HAL_DMAMUX_REQ_GEN_RISING_FALLING  DMAMUX_RGxCR_GPOL 
  • RequestNumber

每次觸發訊號後,可以執行的DMA請求次數,這個在本章的2.3小節已經進行了詳細說明。

39.3.2 同步觸髮結構體HAL_DMA_MuxSyncConfigTypeDef

HAL_DMA_MuxSyncConfigTypeDef的定義如下::

typedef struct  {    uint32_t SyncSignalID;    uint32_t SyncPolarity;    FunctionalState SyncEnable;    FunctionalState EventEnable;    uint32_t RequestNumber;  }HAL_DMA_MuxSyncConfigTypeDef;

下面將這五個結構體成員一 一為大家做個說明。

  • SyncSingnalID

同步觸發源的ID選擇,DMAMUX1可以選擇的觸發源ID如下:

#define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT   0U  #define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT   1U  #define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT   2U  #define HAL_DMAMUX1_SYNC_LPTIM1_OUT        3U  #define HAL_DMAMUX1_SYNC_LP TIM2_OUT       4U  #define HAL_DMAMUX1_SYNC_LPTIM3_OUT        5U  #define HAL_DMAMUX1_SYNC_EXTI0             6U  #define HAL_DMAMUX1_SYNC_TIM12_TRGO        7U 

DMAMUX2可以選擇的觸發源ID如下:

#define HAL_DMAMUX2_SYNC_DMAMUX2_CH0_EVT   0U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH1_EVT   1U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH2_EVT   2U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH3_EVT   3U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH4_EVT   4U  #define HAL_DMAMUX2_SYNC_DMAMUX2_CH5_EVT   5U  #define HAL_DMAMUX2_SYNC_LPUART1_RX_WKUP   6U  #define HAL_DMAMUX2_SYNC_LPUART1_TX_WKUP   7U  #define HAL_DMAMUX2_SYNC_LPTIM2_OUT        8U  #define HAL_DMAMUX2_SYNC_LPTIM3_OUT        9U  #define HAL_DMAMUX2_SYNC_I2C4_WKUP        10U  #define HAL_DMAMUX2_SYNC_SPI6_WKUP        11U  #define HAL_DMAMUX2_SYNC_COMP1_OUT        12U  #define HAL_DMAMUX2_SYNC_RTC_WKUP         13U  #define HAL_DMAMUX2_SYNC_EXTI0            14U  #define HAL_DMAMUX2_SYNC_EXTI2            15U  
  • SyncPolarity

同步觸發訊號的極性設置,可以是上升沿觸發、下降沿觸發或者雙沿觸發。

#define HAL_DMAMUX_SYNC_NO_EVENT        0x00000000U  #define HAL_DMAMUX_SYNC_RISING          DMAMUX_CxCR_SPOL_0  #define HAL_DMAMUX_SYNC_FALLING         DMAMUX_CxCR_SPOL_1  #define HAL_DMAMUX_SYNC_RISING_FALLING  DMAMUX_CxCR_SPOL   
  • SyncEnable

用於使能同步觸發,參數可以是ENABLE 或者 DISABLE。

  • EventEnable

同步觸發事件輸出使能,當參數RequestNumber的數值減到0的時候才會輸出。

  • RequestNumber

每次同步觸發訊號後,可以執行的DMA請求次數,這個在本章的2.4小節已經進行了詳細說明。

39.3.3 DMAMUX的狀態標誌清除問題

DMAMUX有兩個中斷,一個是請求復用器通道發生同步事件溢出,另一個是請求發生器通道發生觸發事件溢出。

當用戶調用了函數HAL_DMA_Start_IT,程式程式碼中會根據用戶是否使能了請求復用器或者請求發生器通道來使能這兩個中斷。

HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)  {      /* 省略未寫 */        if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)      {        /* 使能同步溢出中斷 */        hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;      }        if(hdma->DMAmuxRequestGen != 0U)      {        /* 使能請求發生器的溢出中斷 */        hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;      }        /* 省略未寫 */    }

這兩個中斷產生的中斷標誌是在函數HAL_DMAEx_MUX_IRQHandler裡面做的清除,如果大家不使用HAL庫提供的這個中斷處理函數,就需要自己編寫程式碼清除。

void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)  {    /* 檢測DMAMUX同步溢出 */    if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)    {      /* 禁止同步溢出中斷 */      hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;        /* 清除DMAMUX同步溢出標誌 */      hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;        /* Update error code */      hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;        if(hdma->XferErrorCallback != NULL)      {        /* 回調函數 */        hdma->XferErrorCallback(hdma);      }    }      if(hdma->DMAmuxRequestGen != 0)    {     /* 檢測請求發生器溢出 */      if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)      {        /* 禁止請求發生器溢出中斷 */        hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;          /* 清除DMAMUX請求發生器溢出標誌 */        hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;          /* 更新錯誤程式碼標識 */        hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;          if(hdma->XferErrorCallback != NULL)        {          /* 回調函數 */          hdma->XferErrorCallback(hdma);        }      }    }  }

39.3.4 DMAMUX初始化流程總結

DMAMUX沒有單獨的初始化流程,要結合第40章和42章的函數一起使用。

39.4 源文件stm32h7xx_hal_dma_ex.c

DMAMUX用到如下四個說明,這裡把這四個函數的使用為大家做個說明:

  •   HAL_DMAEx_ConfigMuxSync
  •   HAL_DMAEx_ConfigMuxRequestGenerator
  •   HAL_DMAEx_EnableMuxRequestGenerator
  •   HAL_DMAEx_DisableMuxRequestGenerator

39.4.1 函數HAL_DMAEx_ConfigMuxSync

函數原型:

HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)  {    uint32_t syncSignalID = 0;    uint32_t syncPolarity = 0;      /* 檢測參數 */    assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));    assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));    assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));    assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));      /* 檢測是否使能了同步觸發 */    if(pSyncConfig->SyncEnable == ENABLE)    {      assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig->SyncPolarity));        if(IS_D2_DMA_INSTANCE(hdma) != 0U)      {        assert_param(IS_D2_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));      }      else      {        assert_param(IS_D3_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));      }      syncSignalID = pSyncConfig->SyncSignalID;      syncPolarity = pSyncConfig->SyncPolarity;    }      /* 檢測DMA是否處於就緒態 */    if(hdma->State == HAL_DMA_STATE_READY)    {      /* 上鎖 */      __HAL_LOCK(hdma);        /* 應用新的配置前禁止同步和產生同步事件 */      CLEAR_BIT(hdma->DMAmuxChannel->CCR,(DMAMUX_CxCR_SE | DMAMUX_CxCR_EGE));        /* 配置新的參數,同時DMAMUX_CxCR_DMAREQ_ID 位保持不變 */      MODIFY_REG( hdma->DMAmuxChannel->CCR,                  (~DMAMUX_CxCR_DMAREQ_ID) ,                  (syncSignalID << POSITION_VAL(DMAMUX_CxCR_SYNC_ID))       |                  ((pSyncConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_CxCR_NBREQ)) |                  syncPolarity | (pSyncConfig->SyncEnable << DMAMUX_POSITION_CxCR_SE)    |                  (pSyncConfig->EventEnable << DMAMUX_POSITION_CxCR_EGE));          /* 開鎖 */      __HAL_UNLOCK(hdma);        return HAL_OK;    }    else    {      /* 設置錯誤標誌 */      hdma->ErrorCode = HAL_DMA_ERROR_BUSY;        /* 返回狀態HAL_ERROR */      return HAL_ERROR;    }  }

函數描述:

此函數用於配置DMAMUX的同步觸發,可以用來控制DMAMUX的輸入端的DMA外設請求到輸出端的同步控制,其實就是控制何時輸出。

函數參數:

  •   第1個參數是DMA_HandleTypeDef類型結構體指針變數,用於配置DMA的初始化參數。
  •   第2個參數是HAL_DMA_MuxSyncConfigTypeDef類型結構體變數,參數成員的含義在本章的3.2小節有講解說明。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

注意事項:

  1. 第1個參數的結構體成員介紹在第40章進行了講解。
  2. 調用此函數前要先調用函數HAL_DMA_Init配置好DMA。

使用舉例:

此函數的舉例可以看此貼:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=88925

39.4.2 函數HAL_DMAEx_ConfigMuxRequestGenerator

函數原型:

HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)  {    HAL_StatusTypeDef status = HAL_OK;      /* 檢查參數 */    assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));      if(IS_D2_DMA_INSTANCE(hdma) != 0U)    {      assert_param(IS_D2_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));    }    else    {      assert_param(IS_D3_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));    }      assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));    assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));      /* 如果DMA配置中未使用DMAMUX的請求發生器,返回HAL_ERROR */    if(hdma->DMAmuxRequestGen == 0U)    {      /* 設置參數錯誤 */      hdma->ErrorCode = HAL_DMA_ERROR_PARAM;        /* 設置錯誤狀態 */      status = HAL_ERROR;    }    /* 必須保證請求發生器是關閉的才可以配置 */    else if((hdma->State == HAL_DMA_STATE_READY) && ((hdma->DMAmuxRequestGen->RGCR & DMAMUX_RGxCR_GE) == 0))    {        /* 上鎖 */      __HAL_LOCK(hdma);        /* 設置新參數 */      hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID |                                     ((pRequestGeneratorConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_RGxCR_NBREQ))|                                     pRequestGeneratorConfig->Polarity;      /* 解鎖 */      __HAL_UNLOCK(hdma);        return HAL_OK;    }    else    {      /* 設置錯誤標誌 */      hdma->ErrorCode = HAL_DMA_ERROR_BUSY;        /* 設置錯誤狀態 */      status = HAL_ERROR;    }      return status;  }

函數描述:

此函數用於配置DMAMUX的發生器。請求觸發器最大的優勢就是可以讓不支援DMA傳輸的外設也可以通過Trigger inputs介面觸發DMA傳輸,比如我們可以將RAM中的數據通過定時器觸發直接輸出到GPIO,就可以產生各種脈衝效果,這樣就比較靈活了。

函數參數:

  •   第1個參數是DMA_HandleTypeDef類型結構體指針變數,用於配置DMA的初始化參數。
  •   第2個參數是HAL_DMA_MuxRequestGeneratorConfigTypeDef f類型結構體變數,參數成員的含義在本章的3.1小節有講解說明。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

注意事項:

  1. 第1個參數的結構體成員介紹在第40章進行了講解。
  2. 調用此函數前要先調用函數HAL_DMA_Init配置好DMA。

使用舉例:

HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams ={0}    dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT;   /* 請求觸發器選擇LPTIM2_OUT */  dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING; /* LPTIM2輸出的上升沿和下降沿均可觸發  */  dmamux_ReqGenParams.RequestNumber = 1;                            /* 觸發後,傳輸進行1次DMA傳輸 */  HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams); /* 配置DMAMUX */  HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle);                      /* 使能DMAMUX請求發生器 */   

39.4.3 函數HAL_DMAEx_EnableMuxRequestGenerator

函數原型:

HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma)  {    /* 檢測參數 */    assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));      /* 如果DMA配置中使用了DMAMUX的請求發生器,則將其使能並返回HAL_OK */    if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))    {        /* 使能請求發生器 */      hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE;       return HAL_OK;   }   else   {     return HAL_ERROR;   }  }

函數描述:

調用函數HAL_DMAEx_ConfigMuxRequestGenerator配置了請求發生器後,就可以調用此函數使能請求發生器。跟禁止函數HAL_DMAEx_DisableMuxRequestGenerator是一對。

函數參數:

  •   第1個參數是DMA_HandleTypeDef類型結構體指針變數。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

使用舉例:

HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams ={0}    dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT;   /* 請求觸發器選擇LPTIM2_OUT */  dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING; /* LPTIM2輸出的上升沿和下降沿均可觸發  */  dmamux_ReqGenParams.RequestNumber = 1;                            /* 觸發後,傳輸進行1次DMA傳輸 */  HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams); /* 配置DMAMUX */  HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle);                      /* 使能DMAMUX請求發生器 */

39.4.4 函數HAL_DMAEx_DisableMuxRequestGenerator

函數原型:

HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma)  {    /* 檢查參數 */    assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));    /* 如果DMA配置中使用了DMAMUX的請求發生器,則將其禁止並返回HAL_OK */    if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))    {        /* 禁止請求發生器 */      hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE;       return HAL_OK;   }   else   {     return HAL_ERROR;   }  }

函數描述:

此函數用于禁止請求發生器,跟使能函數HAL_DMAEx_EnableMuxRequestGenerator是一對,

函數參數:

  •   第1個參數是DMA_HandleTypeDef類型結構體指針變數。

使用舉例:

此函數跟前面的HAL_DMAEx_EnableMuxRequestGenerator是一對,使用時直接調用即可。

39.5 總結

本章節就為大家講解這麼多,DMXMUX用到的地方比較多,這幾個常用的函數要熟練掌握。