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