1、DMA介紹
DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAM與I/O設備開辟一條直接傳送數據的通路,能使CPU的效率大為提高。
STM32F103內部有2個DMA控制器(DMA2僅存大容量產品中),DMA1有7個通道,DMA2有5個通道。每個通道專門用來管理來自于一個或多個外設對存儲器訪問的請求,一個仲裁器來協調各個DMA請求的優先權。
DMA有以下特性
- 每個通道都直接連接專用的硬件DMA請求,每個通道都支持軟件觸發。通過軟件來配置。
- 優先權可以通過軟件編程設置,有四個等級:很高、高、中、低,優先權相同時由硬件決定。
- 獨立源和目標數據區的傳輸寬度,可以根據字節、半字、全字,模擬打包和拆包過程。源和目標地址必須按照數據傳輸寬度對齊。
- 支持循環的緩沖器管理。
- 每個通道有3個事件標志:DMA半傳輸、DMA傳輸完成、DMA傳輸出錯,3個事件標志邏輯或成為一個獨立中斷請求。
- 存儲器和存儲器間的傳輸。
- 外設和存儲器,存儲器和外設的傳輸。
- 閃存、SRAM、外設SRAM、APB1、APB2、AHB外設都可以作為訪問的源和目標。
- 最大傳輸數目:65536
1.1、DMA框圖
STM32F103ZET6有兩個DMA控制器,DMA1和DMA2。
- ①DMA請求: 外設想要通過DMA來傳輸數據,必須先給DMA控制器發送DMA請求,DMA收到請求信號后,控制器會給外設一個應答信號,當外設應答后且DMA控制器收到應答信號后,就會啟動DMA傳輸,直到傳輸完畢。
- ②通道:DMA具有12個獨立可編程的通道,其中DMA1有7個通道,DMA2有5個通道,每個通道對應不同的外設的DMA請求。雖然每個通道可以接收多個外設的請求,但是同一時間只能接收一個,不能同時接收多個。
- ③仲裁器:當發生多個DMA通道請求時,就會由仲裁器管理,仲裁器管理DMA通道請求分為兩個階段。第一階段屬于軟件階段,可以在DMA_CCRx寄存器中設置,有4個等級:非常高,高,中和低四個優先級。第二階段屬于硬件階段,兩個或以上的DMA通道請求設置的優先級一樣,則他們優先級取決于通道編號,編號越低優先權越高,比如通道0高于通道1。DMA1控制器擁有高于DMA2控制器的優先級。
1.2、DMA請求映射表
2、DMA函數
DMA_HandleTypeDef結構體類型指針變量:
typedef struct __DMA_HandleTypeDef {void *Instance; /* 寄存器基地址 */DMA_InitTypeDef Init; /* DAM 通信參數 */HAL_LockTypeDef Lock; /* DMA 鎖對象 */ __IO HAL_DMA_StateTypeDef State; /* DMA 傳輸狀態 */ void *Parent; /* 父對象狀態,HAL庫處理的中間變量 */ void(*XferCpltCallback)( struct __DMA_HandleTypeDef *hdma); /*DMA傳輸完成回調*/ void(* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA一半傳輸完成回調 */void(* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); /* DMA傳輸完整的Memory1回調 */void(* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA傳輸半完全內存回調 */void(* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);/*DMA傳輸錯誤回調*/void(* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA傳輸中止回調 */__IO uint32_t ErrorCode; /* DMA存取錯誤代碼 */DMA_TypeDef *DmaBaseAddress; /* DMA通道基地址 */uint32_t ChannelIndex; /* DMA通道索引 */ }DMA_HandleTypeDef;
- Instance:是用來設置寄存器基地址,如果設置的對象是串口1的發送,串口1的DMA傳輸需要用到的是DMA1的通道4,即DMA1_Channel4。
- Parent:是HAL庫處理中間變量,用來指向DMA通道外設句柄。
- XferCpltCallback:傳輸完成回調函數入口地址
- XferHalfCpltCallback:半傳輸完成回調函數入口地址
- XferM1CpltCallback:Memory1傳輸完成回調函數入口地址
- XferErrorCallback:傳輸錯誤回調函數入口地址
- Init:它是DMA_InitTypeDef結構體類型變量
typedef struct { 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優先級:低/中/高/非常高 */ }DMA_InitTypeDef;
- HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);DMA的初始化函數
- __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1時鐘使能 */ __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2時鐘使能 */
- __HAL_LINKDMA(&g_uart1_handler, hdmatx, g_dma_handle);連接DMA和外設句柄。
- 外設的DMA發送、啟動傳輸函數。
- __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4);查詢DMA傳輸通道的狀態
- __HAL_DMA_GET_COUNTER(&g_dma_handle);獲取當前傳輸剩余數據量
- __HAL_DMA_SET_COUNTER (&g_dma_handle, 1000);設置對應的DMA數據流傳輸的數據量大小
- DMA中斷函數
- DMA中斷對于每個通道都有一個中斷服務函數
- HAL庫提供了通用DMA中斷處理函數HAL_DMA_IRQHandler, 在該函數內部,會對DMA傳輸狀態進行分析,然后調用相應的中斷處理回調函數:
- 發送完成回調函數
- 發送一般回調函數
- 接收完成回調函數
- 接收一半回調函數
- 傳輸錯誤回調函數