STM32CubeMX教程12 DMA 直接内存读取
使用STM32CubeMX軟件配置STM32F407開發(fā)板上串口USART1進行DMA傳輸數(shù)據(jù),然后實現(xiàn)與實驗“STM32CubeMX教程9 USART/UART 異步通信”相同的目標
1、準備材料
開發(fā)板(正點原子stm32f407探索者開發(fā)板V2.4)
ST-LINK/V2驅(qū)動
STM32CubeMX軟件(Version 6.10.0)
keil μVision5 IDE(MDK-Arm)
CH340G Windows系統(tǒng)驅(qū)動程序(CH341SER.EXE)
XCOM V2.6串口助手
3、實驗流程
3.0、前提知識
直接存儲器訪問(DMA)是實現(xiàn)存儲器與外設(shè)、存儲器與存儲器之間高效傳輸數(shù)據(jù)的一種方法,其擁有①從外設(shè)到存儲器、②從存儲器到外設(shè)和③從存儲器到存儲器三種傳輸模式,STM32F407有DMA1和DMA2兩個DMA控制器,其中DMA2可以實現(xiàn)上述三種傳輸模式,DMA1僅可以實現(xiàn)前兩種傳輸模式
每個DMA均有8個流(stream),每個流又有8個通道,但是每個流只能同時使用8個通道中的一個,支持DMA的外設(shè)一般可以選擇8個流共64個通道中的某2個通道發(fā)起DMA請求,當(dāng)多個流共同發(fā)起DMA請求時,由DMA仲裁器來決定誰先發(fā)送(軟件可以配置DMA流的優(yōu)先級),如下圖所示為STM32F407的DMA1/2具體的外設(shè)請求映射表(注釋1)
舉個例子:當(dāng)使用USART1_TX發(fā)起DMA請求時,USART1_TX可以選擇的DMA通道只有DMA2 Stream7 CH4,因此DMA請求從DMA2 Stream7 CH4發(fā)起,然后經(jīng)過仲裁器到存儲器端口處取要發(fā)送的數(shù)據(jù),然后經(jīng)過FIFO(可以配置不使用),最后將數(shù)據(jù)送到外設(shè)端口USART1,上述描述如下圖中黃色標注所示(注釋1)
在使用DMA傳輸數(shù)據(jù)時一般需要設(shè)置①DMA請求和②DMA流兩個主要參數(shù),其中DMA請求就是存儲器或者外設(shè)發(fā)起的傳輸需求,而DMA流就是進行DMA傳輸?shù)臄?shù)據(jù)鏈路(上圖黃色鏈路)
使用某個外設(shè)的DMA傳輸時,一般流程為“添加外設(shè)具體的DMA請求 -> 選擇該DMA請求的流Stream ->設(shè)置DMA優(yōu)先級 -> 設(shè)置DMA請求模式 -> 設(shè)置地址遞增(一般為外設(shè)地址不變,內(nèi)存地址遞增) -> 配置FIFO -> 配置傳輸數(shù)據(jù)的數(shù)據(jù)寬度 -> 啟動DMA流全局中斷 -> 在程序中以DMA方式啟動外設(shè)”
先入先出(FIFO)可以想象成一個緩存區(qū),啟用FIFO之后,可以將輸出暫存在該緩存區(qū)中,然后當(dāng)數(shù)據(jù)量一旦達到了FIFO設(shè)置的閾值才會從緩存區(qū)中取出來發(fā)送出去,當(dāng)DMA傳輸?shù)脑春湍繕说臄?shù)據(jù)寬度不同時,F(xiàn)IFO將變得非常有用(可以在FIFO中改變傳輸數(shù)據(jù)的寬度)
3.1、CubeMX相關(guān)配置
請先閱讀“STM32CubeMX教程1 工程建立”實驗3.4.1小節(jié)配置RCC和SYS
3.1.1、時鐘樹配置
系統(tǒng)時鐘樹配置均設(shè)置為STM32F407總線能達到的最高時鐘頻率,無需使用LSE,具體如下圖所示
3.1.2、外設(shè)參數(shù)配置
具體配置如下圖所示,下面對每個序號配置做詳細說明
- 在Pinout & Configuration頁面左邊功能分類欄目Connectivity中單擊其中USART1,在頁面中間USART1 Mode and Configuration中將串口模式設(shè)置為異步通信工作模式,無硬件流控制,然后在Configuration頁面中設(shè)置USART1的相關(guān)參數(shù),具體的USART1基本參數(shù)配置與實驗“STM32CubeMX USART/UART異步通信”相同,在頁面下方的參數(shù)配置欄上面會有很多標簽,當(dāng)前處于的位置為參數(shù)設(shè)置
- 單擊DMA Settings進入USART1的DMA配置頁面,支持DMA功能的外設(shè)在這里都會有DMA Settings頁面
- 單擊ADD按鍵來增加外設(shè)的DMA,如果有可以使用的DMA流則會以列表形式供用戶選擇,這里可以選擇發(fā)送TX和接收RX兩個串口的DMA請求
- 選擇可用的DMA流,DMA的方向會根據(jù)用戶選擇的DMA請求自動推斷,一般只有一個選項,接著選擇DMA流的優(yōu)先級(注意與DMA中斷優(yōu)先級區(qū)分)
- 設(shè)置USART_RX的DMA模式為循環(huán)模式,并設(shè)置地址遞增,由于外設(shè)USART1的地址固定,因此不需要地址遞增,而接收的數(shù)據(jù)存儲到內(nèi)存里需要地址遞增的存儲
- 下方左側(cè)為配置是否使用FIFO,如果使用則需要配置閾值,右邊配置外設(shè)和內(nèi)存的數(shù)據(jù)寬度,由于串口傳輸數(shù)據(jù)是以字節(jié)方式傳輸,存儲也是,因此這里均選擇Byte,下方為突發(fā)傳輸設(shè)置,當(dāng)不使用FIFO時只能為單次傳輸,而當(dāng)使用FIFO時,突發(fā)傳輸可以配置為4、8或16增量突發(fā)傳輸
3.1.3、外設(shè)中斷配置
在Pinout & Configuration頁面左邊System Core/NVIC中勾選USART1和DMA2 stream2/7全局中斷,然后選擇合適的中斷優(yōu)先級即可,步驟如下圖所示
3.2、生成代碼
請先閱讀“STM32CubeMX教程1 工程建立”實驗3.4.3小節(jié)配置Project Manager
單擊頁面右上角GENERATE CODE生成工程
3.2.1、外設(shè)初始化調(diào)用流程
在生成的工程主函數(shù)main()中調(diào)用MX_DMA_Init()函數(shù)對USART1 RX/TX用到的DMA時鐘及其流的中斷進行了配置
在MX_USART1_UART_Init()函數(shù)中相比較于“STM32CubeMX教程9 USART/UART 異步通信”實驗增加了USART1 RX/TX DMA相關(guān)的參數(shù)配置及初始化
3.2.2、外設(shè)中斷調(diào)用流程
勾選DMA2 stream2/7全局中斷后,會在生成的工程文件stm32f4xx_it.c中新增全局中斷函數(shù)DMA2_Stream2_IRQHandler()和DMA2_Stream7_IRQHandler()
這兩個中斷服務(wù)函數(shù)均調(diào)用了HAL庫的DMA中斷統(tǒng)一管理函數(shù)HAL_DMA_IRQHandler(),該函數(shù)中根據(jù)各種標志判斷DMA傳輸完成/失敗/一半完成等事件,然后根據(jù)不同的事件調(diào)用不同的回調(diào)函數(shù),這里DMA傳輸完成之后調(diào)用了hdma->->XferCpltCal1back(),這是個函數(shù)指針
上述過程如下圖所示
這個函數(shù)指針在以DMA方式啟動USART1發(fā)送或者接收數(shù)據(jù)時被指向DMA傳輸完成回調(diào)UART_DMATransmitCpl()函數(shù)
在該DMA傳輸完成回調(diào)UART_DMATransmitCplt()函數(shù)中最終調(diào)用了USART1_TX傳輸完成回調(diào)HAL_UART_TxCpltCallback()函數(shù),該函數(shù)在串口實驗中我們重新實現(xiàn)過,也就是說DMA最終的傳輸完成中斷回調(diào)函數(shù)使用了外設(shè)的中斷回調(diào)函數(shù)
其他的中斷事件回調(diào)流程類似,上述過程如下圖所示
3.2.3、添加其他必要代碼
本實驗與“STM32CubeMX教程9 USART/UART 異步通信”實驗代碼一致,除以下三個方面需要修改
①將主函數(shù)開始的以中斷方式啟動的串口接收函數(shù)修改為以DMA方式啟動的HAL_UART_Receive_DMA函數(shù)
②主循環(huán)中將以中斷方式啟動的串口發(fā)送函數(shù)修改為以DMA方式啟動的HAL_UART_Transmit_DMA函數(shù)
③刪除空閑回調(diào)函數(shù)中的再次啟動串口接收函數(shù)HAL_UART_Receive_IT(huart, rxBuffer, RX_CMD_LEN)
其他所有代碼無需修改,具體修改后的代碼如下所示
為什么刪除再次啟動串口接收中斷的函數(shù)?
在串口章節(jié)的實驗中,我們提到當(dāng)以中斷方式啟動串口接收之后,串口接收完畢一次就不能自動接收第二次了,用戶必須手動再次調(diào)用中斷接收函數(shù)才可以重新接收,因此我們才在串口空閑回調(diào)函數(shù)里重新啟用,以此來實現(xiàn)無限次的自動接收
但是在本實驗中,我們已經(jīng)配置了串口USART1的DMA接收模式為循環(huán)模式,在該模式下其接收完畢一次之后能夠繼續(xù)接收,因此不需要我們在空閑回調(diào)函數(shù)中重新啟用
如果將串口USART1的DMA發(fā)送模式配置為循環(huán)模式,當(dāng)按下按鍵觸發(fā)時,會出現(xiàn)一直發(fā)送的情況,讀者可以嘗試嘗試,這顯然不符合我們的預(yù)想,因此串口USART1的DMA發(fā)送模式配置為了普通模式
4、常用函數(shù)
/*以DMA方式啟動USART接收*/
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
/*以DMA方式啟動USART傳輸*/
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
5、燒錄驗證
5.1、具體步驟
“使用‘STM32CubeMX STM32F4 HAL庫 USART/UART異步通信’實驗的STM32CubeMX工程 -> 增加配置USART1的DMA相關(guān)設(shè)置 -> NVIC中啟動DMA的全局中斷并選擇合適的中斷優(yōu)先級 -> 在生成的代碼上進行3處修改(修改內(nèi)容參看3.2小節(jié))”
5.2、實驗現(xiàn)象
實驗現(xiàn)象與“STM32CubeMX USART/UART異步通信”實驗現(xiàn)象一致
6、注釋詳解
注釋1:圖片來自STM32F4xx中文參考手冊 RM0090
參考資料
STM32Cube高效開發(fā)教程(基礎(chǔ)篇)
更多內(nèi)容請瀏覽 OSnotes的CSDN博客
總結(jié)
以上是生活随笔為你收集整理的STM32CubeMX教程12 DMA 直接内存读取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Prometheus 监控告警系统搭建(
- 下一篇: 神经网络优化篇:理解mini-batch