STM32F4 HAL库开发 -- DMA
一、DMA簡介
DMA之前有講過,參看:STM32開發 – DMA詳解
DMA,全稱為Direct Memory Access,即直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAM與I/O設備開辟一條直接傳送數據的通路,能使CPU的效率大為提高。
STM32F407最多有2個DMA控制器(DMA1和DMA2),共16個數據流(每個控制器8個),每一個DMA控制器都用于管理一個或多個外設的存儲訪問請求。每個數據流總共可以有多大8個通道(或稱為請求)。每個數據流通道都有一個仲裁器,用于處理DMA請求間的優先級。
二、映射表
DMA1的各數據流通道映射表:
DMA2的各數據流通道映射表:
三、函數
1、使能、失能DMA時鐘
DMA的時鐘使能是通過AHB1ENR寄存器來控制的,這里我們要先使能時鐘,才可以配置DMA相關寄存器。HAL庫方法為:
__HAL_RCC_DMA2_CLK_ENABLE();//DMA2 時鐘使能 __HAL_RCC_DMA1_CLK_ENABLE();//DMA1 時鐘使能__HAL_RCC_DMA1_CLK_DISABLE();//禁止 DMA1 時鐘 __HAL_RCC_DMA2_CLK_DISABLE();//禁止 DMA2 時鐘2、初始化DMA2
DMA的某個數據流各種配置參數初始化是通過HAL_DMA_Init函數實現的,該函數聲明為:
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)該函數只有一個DMA_HandleTypeDef 結構體指針類型入口參數,結構體定義為:
typedef struct __DMA_HandleTypeDef {DMA_Stream_TypeDef *Instance; /*!< Register base address */DMA_InitTypeDef Init; /*!< DMA communication parameters */ HAL_LockTypeDef Lock; /*!< DMA locking object */ __IO HAL_DMA_StateTypeDef State; /*!< DMA transfer state */void *Parent; /*!< Parent object state */ void (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete callback */void (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA Half transfer complete callback */void (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete Memory1 callback */void (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer Half complete Memory1 callback */void (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer error callback */void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer Abort callback */ __IO uint32_t ErrorCode; /*!< DMA Error code */uint32_t StreamBaseAddress; /*!< DMA Stream Base Address */uint32_t StreamIndex; /*!< DMA Stream Index */}DMA_HandleTypeDef;成員變量 Instance 是用來設置寄存器基地址,例如要設置為 DMA2 的數據流 7,那么取值為 DMA2_Stream7。
成員變量 Parent 是 HAL 庫處理中間變量,用來指向 DMA 通道外設句柄。
成員變量 XferCpltCallback(傳輸完成回調函數) , XferHalfCpltCallback(半傳輸完成回調函數) , XferM1CpltCallback( Memory1 傳輸完成回調函數)和 XferErrorCallback(傳輸錯誤回調函數)是四個函數指針,用來指向回調函數入口地址。
成員變量 StreamBaseAddress 和 StreamIndex 是數據流基地址和索引號,這個是 HAL 庫處理的時候會自動計算,用戶無需設置。
其他成員變量HAL庫處理過程狀態標識變量,不做過多講解。接下來我們著重介紹成員變量Init,它是DMA_InitTypeDef結構體類型,該結構體定義為:
typedef struct { uint32_t Channel; //通道,例如: DMA_CHANNEL_4 uint32_t Direction;//傳輸方向,例如存儲器到外設 DMA_MEMORY_TO_PERIPH uint32_t PeriphInc;//外設(非)增量模式,非增量模式 DMA_PINC_DISABLE uint32_t MemInc;//存儲器(非)增量模式,增量模式 DMA_MINC_ENABLE uint32_t PeriphDataAlignment; //外設數據大小: 8/16/32 位。 uint32_t MemDataAlignment; //存儲器數據大小: 8/16/32 位。 uint32_t Mode;//模式:外設流控模式/循環模式/普通模式 uint32_t Priority; //DMA 優先級:低/中/高/非常高 uint32_t FIFOMode;//FIFO 模式開啟或者禁止 uint32_t FIFOThreshold; //FIFO 閾值選擇: uint32_t MemBurst; //存儲器突發模式:單次/4 個節拍/8 個節拍/16 個節拍 uint32_t PeriphBurst; //外設突發模式:單次/4 個節拍/8 個節拍/16 個節拍 }DMA_InitTypeDef;具體usart使用DMA的配置如下:
/* USART1_TX Init */hdma_usart1_tx.Instance = DMA2_Stream7;hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_tx.Init.Mode = DMA_NORMAL;hdma_usart1_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);這里大家要注意,HAL庫為了處理各類外設的DMA請求,在調用相關函數之前,需要調用一個宏定義標識符,來連接DMA和外設句柄。例如上面的要使用串口DMA發送,所以方式為:
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);3、使能串口的DMA發送
HAL庫提供了對串口的DMA發送的停止,暫停,繼續等操作函數。
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); //停止 HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); //暫停 HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart);//恢復4、使能DMA數據流
使能DMA數據流的函數為:
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)5、查詢DMA傳輸狀態
查詢DMA傳輸通道的狀態:
__HAL_DMA_GET_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7);獲取當前傳輸剩余數據量:
__HAL_DMA_GET_COUNTER(&UART1TxDMA_Handler);設置對應DMA數據流傳輸的數據量大小:
__HAL_DMA_SET_COUNTER(&UART1TxDMA_Handler,1000);6、DMA中斷使用方法
DMA 中斷對于每個流都有一個中斷服務函數,比如 DMA2_Stream7 的中斷服務函數為DMA2_Stream7_IRQHandler 。 同樣 , HAL 庫 也 提 供 了一 個通 用的 DMA 中 斷處 理函 數HAL_DMA_IRQHandler,在該函數內部,會對 DMA 傳輸狀態進行分析,然后調用相應的中斷處理回調函數:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);//發送完成回調函數 void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);/發送一半回調函數 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收完成回調函數 void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//接收一半回調函數 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);//傳輸出錯回調函數對于串口 DMA 開啟,使能數據流,啟動傳輸,這些步驟,如果使用了中斷,可以直接調用 HAL 庫函數 HAL_USART_Transmit_DMA,該函數聲明如下:
HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size);總結
以上是生活随笔為你收集整理的STM32F4 HAL库开发 -- DMA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网人理想假期VS现实假期
- 下一篇: 红人职业化发展报告