文本提供的代碼是基于STM32CubeMX生成的HAL庫的。
STM32串口接收大體分為3種方式:
1、阻塞接收---HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
2、中斷接收---HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
3、DMA接收---HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
本文只談?wù)揇MA接收方式,同時增加空閑中斷和多級緩沖。單純的DMA接收適合固定長度的數(shù)據(jù)接收,局限性太大,很難適用實際項目需要。增加空閑中斷,可以做到不定長接收。多級緩沖在一定程度上可以緩解裸機代碼實時性差的問題。
具體步驟如下:
1.STM32CubeMX生成工程,這里介紹串口部分的設(shè)置:
image
2.新建usart_ex.c文件,主要關(guān)注兩個函數(shù):void HW_UART_Modem_IRQHandler(UART_HandleTypeDef *huart)和void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)。
/**
******************************************************************************
* @file : usart_ex.c
* @author : xEndLess
* @version : V1.0.0
* @date : 2018-4-3
* @brief : 本文件是對usart.c的擴展,避免每次用Cube建立工程時,需要對usart.c做出修改.
* 串口發(fā)送函數(shù),回調(diào)函數(shù),DMA接收完成函數(shù),都放在這里。
*
******************************************************************************
*/> /* Includes ------------------------------------------------------------------*/#include 'bsp.h'#include 'stdarg.h'/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*/Usart1_BufTypeDef Usart1Buf;Usart2_BufTypeDef Usart2Buf;Usart3_BufTypeDef Usart3Buf;Usart4_BufTypeDef Usart4Buf;Usart5_BufTypeDef Usart5Buf;/* 以下4個變量是在uasrt.c中定義的 ,Cube自動生成 */extern DMA_HandleTypeDef hdma_uart4_rx;extern DMA_HandleTypeDef hdma_usart1_rx;extern DMA_HandleTypeDef hdma_usart2_rx;extern DMA_HandleTypeDef hdma_usart3_rx;/* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*//****************** UART CallBack *******************//**
* @brief Rx Transfer completed callback
* @param UartHandle: UART handle
* @note This example shows a simple way to report end of DMA Rx transfer, and
* you can add your own implementation.
* @retval None
*/void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if (huart->Instance == USART1)
{
Usart1Buf.RxEndFlag[Usart1Buf.RxDimension] = SET;
Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] = USART1_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
Usart1Buf.RxDimension++;
Usart1Buf.RxDimension %= USART1_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart1Buf.RxBuffer[Usart1Buf.RxDimension], USART1_BUF_LENGTH);
}
else if (huart->Instance == USART2)
{
Usart2Buf.RxEndFlag[Usart2Buf.RxDimension] = SET;
Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] = USART2_BUF_LENGTH -
__HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
Usart2Buf.RxDimension++;
Usart2Buf.RxDimension %= USART2_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart2Buf.RxBuffer[Usart2Buf.RxDimension], USART2_BUF_LENGTH);
}
else if (huart->Instance == USART3)
{
Usart3Buf.RxEndFlag[Usart3Buf.RxDimension] = SET;
Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] = USART3_BUF_LENGTH -
__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
Usart3Buf.RxDimension++;
Usart3Buf.RxDimension %= USART3_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart3Buf.RxBuffer[Usart3Buf.RxDimension], USART3_BUF_LENGTH);
}
else if (huart->Instance == UART4)
{
Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] = USART4_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);
Usart4Buf.RxEndFlag[Usart4Buf.RxDimension] = SET;
Usart4Buf.RxDimension++;
Usart4Buf.RxDimension %= USART4_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart4Buf.RxBuffer[Usart4Buf.RxDimension], USART4_BUF_LENGTH);
}
else if (huart->Instance == UART5)
{
Usart5Buf.RxEndIndex[Usart5Buf.RxDimension] = USART5_BUF_LENGTH;
Usart5Buf.RxEndFlag[Usart5Buf.RxDimension] = SET;
Usart5Buf.RxDimension++;
Usart5Buf.RxDimension %= USART5_BUF_DIMENSION;
HAL_UART_Receive_IT(huart, Usart5Buf.RxBuffer[Usart5Buf.RxDimension], USART5_BUF_LENGTH);
}}/**
* @brief DMA IDLE接收串口數(shù)據(jù),該函數(shù)剛到串口中斷中
* @param handle to the UART
* @retval void
**/void HW_UART_Modem_IRQHandler(UART_HandleTypeDef *huart){
uint32_t tmp_flag = 0, tmp_it_source = 0;
if (huart->Instance == USART1)
{
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE);
/* UART parity error interrupt occurred ------------------------------------*/
if ((tmp_flag != RESET) && (tmp_it_source != RESET))
{
Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] = USART1_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
/* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */
if (Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] != 0)
{
Usart1Buf.RxEndFlag[Usart1Buf.RxDimension] = SET;
Usart1Buf.RxDimension++;
Usart1Buf.RxDimension %= USART1_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart1Buf.RxBuffer[Usart1Buf.RxDimension], USART1_BUF_LENGTH);
}
}
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
else if (huart->Instance == USART2)
{
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE);
/* UART parity error interrupt occurred ------------------------------------*/
if ((tmp_flag != RESET) && (tmp_it_source != RESET))
{
Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] = USART2_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
/* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */
if (Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] != 0)
{
Usart2Buf.RxEndFlag[Usart2Buf.RxDimension] = SET;
Usart2Buf.RxDimension++;
Usart2Buf.RxDimension %= USART2_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart2Buf.RxBuffer[Usart2Buf.RxDimension], USART2_BUF_LENGTH);
}
}
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
else if (huart->Instance == USART3)
{
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE);
/* UART parity error interrupt occurred ------------------------------------*/
if ((tmp_flag != RESET) && (tmp_it_source != RESET))
{
Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] = USART3_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
/* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */
if (Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] != 0)
{
Usart3Buf.RxEndFlag[Usart3Buf.RxDimension] = SET;
Usart3Buf.RxDimension++;
Usart3Buf.RxDimension %= USART3_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart3Buf.RxBuffer[Usart3Buf.RxDimension], USART3_BUF_LENGTH);
}
}
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
else if (huart->Instance == UART4)
{
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE);
/* UART parity error interrupt occurred ------------------------------------*/
if ((tmp_flag != RESET) && (tmp_it_source != RESET))
{
Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] = USART4_BUF_LENGTH -
__HAL_DMA_GET_COUNTER(&hdma_uart4_rx);
/* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */
if (Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] != 0)
{
Usart4Buf.RxEndFlag[Usart4Buf.RxDimension] = SET;
Usart4Buf.RxDimension++;
Usart4Buf.RxDimension %= USART4_BUF_DIMENSION;
HAL_UART_DMAStop(huart);
HAL_UART_Receive_DMA(huart, Usart4Buf.RxBuffer[Usart4Buf.RxDimension], USART4_BUF_LENGTH);
}
}
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
else if (huart->Instance == UART5)
{
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE);
/* UART parity error interrupt occurred ------------------------------------*/
if ((tmp_flag != RESET) && (tmp_it_source != RESET))
{
Usart5Buf.RxEndIndex[Usart5Buf.RxDimension] = USART5_BUF_LENGTH - huart5.RxXferCount;
上一篇:在stm32f407上移植openharmony遇到的問題
下一篇:意法半導(dǎo)體推出STM32U3微控制器,面向遠程、智能和可持續(xù)應(yīng)用,拓展超低功耗系列創(chuàng)新技術(shù)
推薦閱讀最新更新時間:2025-04-02 12:13






設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- 迅為IMX6開發(fā)板Android應(yīng)用-AndroidStudio-calculator測試
- 玩轉(zhuǎn) ESP32 + Arduino (二十) SIM800L上傳數(shù)據(jù)到OneNet(新版Mqtts)
- 玩轉(zhuǎn) ESP32 + Arduino (二十一) SPIFFS文件系統(tǒng) (已棄用)
- 玩轉(zhuǎn) ESP32 + Arduino (二十二) SIM800L上傳數(shù)據(jù)到阿里IOT(溫濕度和LBS)(NTP對時)
- 玩轉(zhuǎn) ESP32 + Arduino (二十三) 多文件系統(tǒng)及全局變量
- 玩轉(zhuǎn) ESP32 + Arduino (二十四) SD卡讀寫
- 玩轉(zhuǎn) ESP32 + Arduino (二十五) SSD1306庫驅(qū)動OLED
- 玩轉(zhuǎn) ESP32 + Arduino(二十六) 按鍵控制庫 OneButton
- 玩轉(zhuǎn) ESP32 + Arduino(二十七) ESP對象
- XRT83SL38EVAL,基于 XRT83SL38 線路接口單元的評估系統(tǒng)
- 反激式開關(guān)電源
- 【訓(xùn)練營】機械狗制作
- LTC7813MPUH 寬輸入范圍至 12V/8A 低 IQ 級聯(lián)升壓+降壓穩(wěn)壓器的典型應(yīng)用電路 (VMID = 14V)
- 【RA】基于瑞薩RA2E1微處理控制器拓展的觸控燈條
- 基于立創(chuàng)·梁山派的智能LED燈帶遙控器設(shè)計
- 雪花燈2.0
- LT1121CS8 5V 低壓差穩(wěn)壓器的典型應(yīng)用電路,用于具有關(guān)斷的電池供電電源
- 使用 NXP Semiconductors 的 LPC29 的參考設(shè)計
- NUD4001DGEVB:LED 驅(qū)動器版本 A 評估板
- Diodes 公司的精密可調(diào)式限流電源切換器,保護汽車子系統(tǒng)
- 為48V數(shù)據(jù)中心應(yīng)用提供高功率密度開關(guān)電容中間總線轉(zhuǎn)換器
- 安森美的智能技術(shù)將賦能記憶科技下一代服務(wù)器每一個節(jié)點
- 中國研制出5分鐘充滿的鋰電池,技術(shù)全球領(lǐng)先,目前已開始試用
- KST-STM32學習之USART
- 半導(dǎo)體設(shè)備需求大增,華峰測控2021年凈利同比增120%
- 6.蜂鳴器
- 基于Keil C51 集成開發(fā)環(huán)境的仿真與調(diào)試
- 影響嵌入式處理技術(shù)未來發(fā)展的三個趨勢
- 從實驗室到工業(yè)場景:優(yōu)艾智合密集發(fā)布7款人形機器人
- 地表最酷人形機器人,拿下新一輪2億元融資
- 自動駕駛警示:沒有企業(yè)能完全避免自動駕駛在復(fù)雜環(huán)境中的失誤
- 高階就高級嗎?我們到底該如何使用智能駕駛輔助?
- 即將迎來第三代?嵐圖固態(tài)電池研發(fā)進展曝光
- 一文了解2025年3月的固態(tài)電池大事件!
- 傳統(tǒng)鋰電、半固態(tài)、固態(tài)電池終極對決:誰將主宰新能源未來?
- 國產(chǎn)智駕迎戰(zhàn)特斯拉FSD,背后AI含量差幾何?
- 左手AI,右手機器人,半導(dǎo)體巨頭英飛凌的新故事
- 激光雷達的復(fù)仇
- #Micropython大作戰(zhàn)#第二彈:發(fā)表mciropython原創(chuàng)教程贏好禮!
- 樂享MPLAB Xpress云端IDE,開心答題贏禮品
- TI毫米波雷達技術(shù)在工業(yè)上的應(yīng)用
- 基于PolarFire® SoC FPGA的Microchip非對稱多處理(AMP)解決方案
- 不可錯過的一次邂逅,TTI攜TE傳感器樣片與你相見!免費樣片申請活動開始啦~
- 【轉(zhuǎn)發(fā)無最,分享有禮】ADI實驗室電路電子書!
- 樂享愜意春天,TI A8開源硬件平臺體驗季!
- 有獎直播|TE帶您解讀物聯(lián)網(wǎng)中的智能天線設(shè)計趨勢及傳感器應(yīng)用案例
- 有獎活動“庖丁”解智能睡眠監(jiān)測儀,一波“水軍”來圍觀
- 蘋果MicroLED屏幕計劃曝光AR設(shè)備信息:0.7至0.8英寸
- 萊寶高科:暫未開發(fā)出智能手機用柔性觸摸屏樣品
- AI將成2018手機差異化重點
- 工信部:對WiFi萬能鑰匙等蹭網(wǎng)類程序開展調(diào)查
- OPPO宣布成立研究院:圍繞5G、AI、影像、材料工藝等方向研究
- 解決網(wǎng)絡(luò)分析儀通道超差故障
- 多用途電子測量儀器-頻譜分析儀是研究電信號頻譜結(jié)構(gòu)的儀
- LCR測試儀的五種連接方法
- 如何預(yù)防和避免對網(wǎng)絡(luò)分析儀造成損壞
- SIA督促美國取消半導(dǎo)體301關(guān)稅,稱已影響經(jīng)濟