串口通信-DMA方式
1 DMA概述
直接存儲(chǔ)器訪問(wèn) (DMA) : 用于在外設(shè)與存儲(chǔ)器之間以及存儲(chǔ)器與存儲(chǔ)器之間進(jìn)行高速數(shù)據(jù)傳輸。DMA傳輸過(guò)程的初始化和啟動(dòng)由CPU完成,傳輸過(guò)程由DMA控制器來(lái)執(zhí)行,無(wú)需CPU參與,從而節(jié)省CPU資源,提高利用率。
DMA數(shù)據(jù)傳輸?shù)乃膫€(gè)要素:
- 傳輸源 :DMA數(shù)據(jù)傳輸?shù)膩?lái)源
- 傳輸目標(biāo):DMA數(shù)據(jù)傳輸?shù)哪康?/li>
- 傳輸數(shù)量:DMA傳輸數(shù)據(jù)的數(shù)量
- 觸發(fā)信號(hào):?jiǎn)?dòng)一次DMA數(shù)據(jù)傳輸?shù)膭?dòng)作
STM32的DMA控制器特點(diǎn)
- 每個(gè)DMA控制器有8個(gè)數(shù)據(jù)流,每個(gè)數(shù)據(jù)流可以映射到8個(gè)通道(或請(qǐng)求);
- 每一個(gè)DMA控制器用于管理一個(gè)或多個(gè)外設(shè)的存儲(chǔ)器訪問(wèn)請(qǐng)求,并通過(guò)總線仲裁器來(lái)協(xié)調(diào)各個(gè)DMA請(qǐng)求的優(yōu)先級(jí);
- 數(shù)據(jù)流(stream)是用于連接傳輸源和傳輸目標(biāo)的數(shù)據(jù)通路,每個(gè)數(shù)據(jù)流可以配置為不同的傳輸源和傳輸目標(biāo),這些傳輸源和傳輸目標(biāo)稱為通道(Channel);
- 具備16字節(jié)的FIFO。使能FIFO功能后,源數(shù)據(jù)先送入FIFO,達(dá)到FIFO的觸發(fā)閾值后,再傳送到目標(biāo)地址。
DMA數(shù)據(jù)傳輸方式
- 普通模式:傳輸結(jié)束后(即要傳輸數(shù)據(jù)的數(shù)量達(dá)到零),將不再產(chǎn)生DMA操作。若 開(kāi)始新的DMA傳輸,需在關(guān)閉DMA通道情況下,重新啟動(dòng)DMA傳輸。
- 循環(huán)模式:可用于處理環(huán)形緩沖區(qū)和連續(xù)數(shù)據(jù)流(例如ADC掃描模式)。當(dāng)激活循 環(huán)模式后,每輪傳輸結(jié)束時(shí),要傳輸?shù)臄?shù)據(jù)數(shù)量將自動(dòng)用設(shè)置的初始值進(jìn)行加載,并繼續(xù)響應(yīng)DMA請(qǐng)求。
2 DMA方式的接口函數(shù)
串口DMA方式發(fā)送函數(shù):
HAL_UART_Transmit_DMA
函數(shù)原型 HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size)
功能描述 在DMA方式下發(fā)送一定數(shù)量的數(shù)據(jù) 入口參數(shù)1 huart:串口句柄的地址 入口參數(shù) pData:待發(fā)送數(shù)據(jù)的首地址 入口參數(shù)3 Size:待發(fā)送數(shù)據(jù)的個(gè)數(shù) 返回值 HAL狀態(tài)值:HAL_OK表示發(fā)送成功;HAL_ERROR表示參數(shù)錯(cuò)誤;HAL_BUSY表示串口被占用; 注意事項(xiàng) 1. 該函數(shù)將啟動(dòng)DMA方式的串口數(shù)據(jù)發(fā)送2. 完成指定數(shù)量的數(shù)據(jù)發(fā)送后,可以觸發(fā)DMA中斷,在中斷中將調(diào)用發(fā)送中斷回調(diào)函數(shù)HAL_UART_TxCpltCallback進(jìn)行后續(xù)處理3. 該函數(shù)由用戶調(diào)用戶調(diào)用 串口DMA方式接收函數(shù):
HAL_UART_Receive_DMA
函數(shù)原型 HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size)
功能描述 在DMA方式下接收一定數(shù)量的數(shù)據(jù) 入口參數(shù)1 huart:串口句柄的地址 入口參數(shù) pData:待接收數(shù)據(jù)的首地址 入口參數(shù)3 Size:待接收數(shù)據(jù)的個(gè)數(shù) 返回值 HAL狀態(tài)值:HAL_OK表示發(fā)送成功;HAL_ERROR表示參數(shù)錯(cuò)誤;HAL_BUSY表示串口被占用; 注意事項(xiàng) 1. 該函數(shù)將啟動(dòng)DMA方式的串口數(shù)據(jù)接收2. 完成指定數(shù)量的數(shù)據(jù)接收后,可以觸發(fā)DMA中斷,在中斷中將調(diào)用接收中斷回調(diào)函數(shù)HAL_UART_ExCpltCallback進(jìn)行后續(xù)處理3. 該函數(shù)由用戶調(diào)用戶調(diào)用 獲取未傳輸數(shù)據(jù)個(gè)數(shù)函數(shù):
__HAL_DMA_GET_COUNTER
函數(shù)原型 __HAL_DMA_GET_COUNTER
功能描述 獲取DMA數(shù)據(jù)流中未傳輸數(shù)據(jù)的個(gè)數(shù) 參數(shù) HANDLE :串口句柄的地址 返回值 NDTR寄存器的內(nèi)容,即DMA數(shù)據(jù)流中無(wú)傳輸數(shù)據(jù)的個(gè)數(shù) 注意事項(xiàng) 1. 該函數(shù)是宏函數(shù),進(jìn)行宏替換,不發(fā)生函數(shù)調(diào)用2. 該函數(shù)需要由用戶調(diào)用,用于獲取未傳輸數(shù)據(jù)的個(gè)數(shù) 關(guān)閉DMA數(shù)據(jù)流:
__HAL_DMA_DISABLE
函數(shù)原型 __HAL_DMA_DISABLE(__HANDLE__)
功能描述 關(guān)閉指定的DMA數(shù)據(jù)流 參數(shù) HANDLE :串口句柄的地址 返回值 無(wú) 注意事項(xiàng) 1. 該函數(shù)是宏函數(shù),進(jìn)行宏替換,不發(fā)生函數(shù)調(diào)用2. 該函數(shù)需要由用戶調(diào)用,用于關(guān)閉指定的DMA數(shù)據(jù)流3. 關(guān)閉DMA數(shù)據(jù)流后觸發(fā)DMA中斷,最終調(diào)用串口收發(fā)的回調(diào)函數(shù)
任務(wù)實(shí)踐4
不定長(zhǎng)數(shù)據(jù)的收發(fā):利用串口調(diào)試助手,從PC上發(fā)送任意長(zhǎng)度的字符到開(kāi)發(fā)板,開(kāi)發(fā)板收到后原樣發(fā)回到PC。
空閑中斷的特點(diǎn):
- 在一幀數(shù)據(jù)傳輸結(jié)束后,通信線路將會(huì)維持高電平,這個(gè)狀態(tài)稱為空閑狀態(tài);
- 當(dāng)CPU檢測(cè)到通信線路處于空閑狀態(tài)時(shí),且空閑狀態(tài)持續(xù)時(shí)間大于一個(gè)字節(jié)傳輸時(shí)間時(shí),空閑狀態(tài)標(biāo)志IDLE將由硬件置1。如果串口控制寄存器CR1中的IDLEIE位為1,將會(huì)觸發(fā)空閑中斷( IDLE中斷);
- 由于空閑標(biāo)志是在一幀數(shù)據(jù)傳輸完成后才置位,在有效數(shù)據(jù)傳輸過(guò)程中不會(huì)置位,因此借助空閑中斷,可以實(shí)現(xiàn)不定長(zhǎng)數(shù)據(jù)的收發(fā)。
設(shè)計(jì)思路:
使能IDLE中斷,在串口2的中斷服務(wù)程序USART2_IRQHandler中添加對(duì)IDLE中斷的判斷,該函數(shù)位于stm32f4xx_it.c文件;
設(shè)置傳輸模式為普通模式,啟動(dòng)DMA傳輸。串口一旦接收到數(shù)據(jù),則觸發(fā)DMA操作,將數(shù)據(jù)存放到用戶定義的接收緩沖區(qū);
當(dāng)一幀數(shù)據(jù)發(fā)送完成后,線路處于IDLE狀態(tài),將觸發(fā)IDLE中斷,調(diào)用IDLE中斷回調(diào)函數(shù),設(shè)置數(shù)據(jù)接收完成標(biāo)志;
主程序檢測(cè)到接收完成標(biāo)志置位后,將接收的一幀數(shù)據(jù)原樣發(fā)回到PC,并禁能DMA,以觸發(fā)DMA中斷。DMA中斷將調(diào)用接收中斷回調(diào)函數(shù),在回調(diào)函數(shù)中重新啟動(dòng)DMA傳輸。
串口1的DMA配置
DMA數(shù)據(jù)流的中斷使能由CubeMX自動(dòng)勾選,手動(dòng)使能串口2中斷編寫(xiě)程序
在stm32f1xx_it.c
中添加空閑中斷的處理/** * @brief This function handles USART1 global interrupt. */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ // Add handling of idle interrupts if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE != RESET)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); // Clear the IDLE interrupt flag HAL_UART_IdleCpltCallback(&huart1); // User-written IDLE interrupt callback function } /* USER CODE END USART1_IRQn 1 */ }
在
main.c
中添加用戶宏變量、變量定義
/* USER CODE BEGIN PM */ #define LENGTH 100 // Receive buffer size /* USER CODE END PM */ /* USER CODE BEGIN PV */ uint8_t RxBuffer[LENGTH]; uint8_t RecCount = 0; uint8_t RxFlag = 0; /* USER CODE END PV */
聲明和定義空閑中斷回調(diào)函數(shù),定義DMA接收中斷回調(diào)函數(shù)
/* USER CODE BEGIN PFP */ void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart) /* USER CODE END PFP */ /* USER CODE BEGIN 4 */ int fputc (int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart- >Instance == USART1) { HAL_UART_Receive_DMA(&huart1, (uint8_t*)RxBuffer, LENGTH); } } void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart) { RxFlag = 1; } /* USER CODE END 4 */
編寫(xiě)用戶應(yīng)用代碼
/* USER CODE BEGIN 2 */ printf("*** UART coummunication using IDLE IT + DMAn"); pringf("PLease enter arbitrary length characters:n"); __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); HAL_UART_Receive_DMA(&huart1, (uint8_t*)RxBuffer, LENGTH); /* USER CODE END 2 */ /* USER CODE BEGIN 3 */ if (RxFlag == 1) { RxFlag = 0; RecCount = LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); HAL_UART_Transmit_DMA(&huart1, (uint8_t*)RxBuffer, RecCount); RecCount = 0; __HAL_DMA_DISABLE(&hdma_uasrt1_rx); } } /* USER CODE END 3 */
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7637瀏覽量
166453 -
cpu
+關(guān)注
關(guān)注
68文章
11040瀏覽量
216042 -
STM32
+關(guān)注
關(guān)注
2290文章
11017瀏覽量
362469 -
串口通信
+關(guān)注
關(guān)注
34文章
1636瀏覽量
56561 -
dma
+關(guān)注
關(guān)注
3文章
572瀏覽量
102356
發(fā)布評(píng)論請(qǐng)先 登錄
STM32的串口通信基礎(chǔ)知識(shí)點(diǎn)匯總,不看肯定后悔
STM32的串口采用DMA方式發(fā)送數(shù)據(jù)測(cè)試
STM32 串口使用IDLE中斷+DMA接收(HAL庫(kù)函數(shù))

【STM32】使用DMA方式實(shí)現(xiàn)串口數(shù)據(jù)轉(zhuǎn)發(fā)

STM32中斷與串口DMA通信

STM32串口DMA發(fā)送數(shù)據(jù)

STM32 HAL CubeMX 串口IDLE接收空閑中斷+DMA

STM32采用串口DMA方式的USART串口通訊

STM32串口中斷之DMA通信

STM32F103DMA串口通信

評(píng)論