STM32 DMA簡述
STM32 DMA簡述
DMA (Direct Memory Access) 直接內存存儲器,在做數據傳輸時能夠大大減輕CPU的負擔。
DMA的作用
DMA提供了一個關於數據的高數傳輸通道,這個通道不占用CPU的資源。換句話說,通過DMA通道,你在傳輸大規模數據的時候CPU同時也能夠去幹其他事。
你可以控制DMA通道的接入口,靈活配置傳輸的數據源和目的地。以下幾個是常用的DMA傳輸路徑:
從外設到內存
從內存A區域傳到內存B區域
從一個外設傳輸到另一個外設
從內存傳輸數據到外設
....
DMA流程分析
在stm32中,DMA是以類似外設的形式添加到內核之外的,下面我們來看具體的框圖:
從上圖我們可以看到,DMA通過系統總線連接到了APB1和APB2總線,也連接到了SRAM,Flash和Cortex內核。
我們發現,DMA是獨立在內核之外的,其系統總線連接了所有模塊,而且這個連接過程並沒有經過內核。這也印證了前文所說的,在使用DMA通道傳輸數據時,並不占用CPU資源。
再仔細觀察上圖,圖中除了總線之外,還有標有DMA請求字樣的黑色箭頭。外設需要向DMA發送請求,並應答通過後才能夠啟動傳輸。具體過程如下:
①在發生一個事件後,外設發送一個請求信號到DMA控制器。DMA控制器根據通道的優先權處理請求。
②當DMA控制器開始訪問外設的時候,DMA控制器立即發送給外設一個應答信號。
③當外設從DMA控制器得到應答信號時,外設立即釋放它的請求。
④在釋放請求後,DMA控制器撤銷應答信號。
DMA配置
在我們想要使用DMA的時候,我們該怎麽啟用他呢?我們通過一個配置函數來實現,在函數內部設置DMA傳輸的各種參數,最後使能它。代碼如下:
void USARTx_DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; // 開啟DMA時鐘 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 設置DMA源地址:串口數據寄存器地址*/ DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; // 內存地址(要傳輸的變量的指針) DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff; // 方向:從內存到外設 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 傳輸大小 DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; // 外設地址不增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 內存地址自增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 外設數據單位 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 內存數據單位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // DMA模式,一次或者循環模式 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 優先級:中 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // 禁止內存到內存的傳輸 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 配置DMA通道 DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure); // 使能DMA DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE); }
這是一個將串口和DMA連接起來的配置代碼,傳輸方向為從內存到外設。當然想要實現完整的功能,還需要其他代碼,你可以參考機械工業出版社出的那本STM32庫開發實戰指南。
STM32 DMA簡述