STM32 串口 (DMA + 空閑中斷 + 環形緩沖區)

STM32 串口 (DMA + 空閑中斷 + 環形緩沖區)


1. 基本概念

  • UART 空閑中斷(IDLE)

    • 當串口 RX 線上 連續一段時間沒有數據接收,USART 外設觸發 空閑中斷
    • 空閑中斷的主要作用是通知數據傳輸完成或當前幀結束。
  • DMA 接收模式

    • DMA(Direct Memory Access) 自動將串口接收到的數據存儲到指定緩沖區。
    • CPU 不再需要逐字節處理接收數據,提高效率。
    • HAL_UARTEx_ReceiveToIdle_DMA:啟動 DMA 接收,支持接收數據直到觸發 空閑中斷
  • 環形緩沖區

    • 通過固定大小的緩沖區 + 讀寫指針 實現數據的循環存儲。
    • 用于連續接收數據,解決 DMA 數據處理問題。
    • 讀寫指針邏輯:
      • 寫指針:指向新接收數據的位置。
      • 讀指針:指向待處理數據的位置。

2. 流程概述

  1. 初始化 UART 和 DMA

    • 配置 UART 和 DMA。
    • 啟用 DMA 接收并啟動 HAL_UARTEx_ReceiveToIdle_DMA
  2. 串口接收數據

    • 數據通過 DMA 存儲到 DMA 緩沖區 uart_rx_dma_buffer
    • 串口數據未停止時,DMA 自動接收,CPU 不參與。
  3. 觸發空閑中斷

    • 當 RX 線上 超過一個字節時間沒有數據接收,觸發 空閑中斷(IDLE)。
    • 調用 USARTx_IRQHandler
  4. 中斷處理

    • USARTx_IRQHandler 中調用 HAL_UART_IRQHandler
    • HAL 庫檢測到 IDLE 中斷,觸發回調函數 HAL_UARTEx_RxEventCallback
  5. 回調函數處理接收數據

    • HAL_UARTEx_RxEventCallback 中:
      • 計算接收到的數據長度。
      • 將 DMA 緩沖區的數據拷貝到 環形緩沖區
      • 清空 DMA 緩沖區,準備下一次接收。
    • 重新啟動 DMA 接收 HAL_UARTEx_ReceiveToIdle_DMA
  6. 主循環讀取數據

    • 通過環形緩沖區的 讀寫指針 提取接收到的數據,進行處理。

3. 代碼展示

初始化 UART 和 DMA
void MX_USART1_UART_Init(void) {huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;HAL_UART_Init(&huart1);// 啟動 DMA 接收HAL_UARTEx_ReceiveToIdle_DMA(&huart1, uart_rx_dma_buffer, sizeof(uart_rx_dma_buffer));__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);  // 禁用半滿中斷
}

中斷服務函數
void USART1_IRQHandler(void) {HAL_UART_IRQHandler(&huart1);  // 處理 UART 中斷
/*不同的觸發,跳轉不同的回調函數,若是空閑中斷觸發,跳轉的是 *`HAL_UARTEx_RxEventCallback`*//* 調用HAL庫的串口中斷處理函數 */HAL_UARTEx_ReceiveToIdle_DMA(&huart1, uart_rx_dma_buffer, sizeof(uart_rx_dma_buffer));/* 重新啟動DMA接收,確保下一次接收正常進行 */ __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
}

回調函數:處理空閑中斷
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {if (huart->Instance == USART1) {if (!ringbuffer_is_full(&usart_rb)) {ringbuffer_write(&usart_rb, uart_rx_dma_buffer, Size);  // 將數據寫入環形緩沖區}memset(uart_rx_dma_buffer, 0, sizeof(uart_rx_dma_buffer));  // 清空 DMA 緩沖區}
}

4. 環形緩沖區實現

環形緩沖區結構
  • ringbuffer_t
    

    結構體用于管理緩沖區:

    • buffer:實際存儲數據的數組。
    • r:讀指針。
    • w:寫指針。
    • itemCount:當前緩沖區內的數據量。
typedef struct {uint32_t w;                        // 寫指針uint32_t r;                        // 讀指針uint8_t buffer[RINGBUFFER_SIZE];   // 數據存儲緩沖區uint32_t itemCount;                // 當前緩沖區數據量
} ringbuffer_t;

函數功能
  1. 初始化環形緩沖區

    • 清零緩沖區、讀寫指針和數據量。
    void ringbuffer_init(ringbuffer_t *rb);
    
  2. 寫入數據

    • 檢查緩沖區是否已滿,未滿時將數據寫入。
    int8_t ringbuffer_write(ringbuffer_t *rb, uint8_t *data, uint32_t num);
    
  3. 讀取數據

    • 檢查緩沖區是否為空,非空時讀取數據。
    int8_t ringbuffer_read(ringbuffer_t *rb, uint8_t *data, uint32_t num);
    
  4. 緩沖區狀態檢查

    • ringbuffer_is_full:檢查緩沖區是否已滿。
    • ringbuffer_is_empty:檢查緩沖區是否為空。

5. 工作順序總結

  1. HAL_UARTEx_ReceiveToIdle_DMA 啟動 DMA 接收。
  2. UART 接收到數據,DMA 將數據存入緩沖區。
  3. 空閑中斷(IDLE)觸發,調用 USART1_IRQHandler
  4. HAL_UART_IRQHandler 檢測到空閑中斷,自動調用 HAL_UARTEx_RxEventCallback
  5. 在回調函數中
    • 處理接收到的數據(寫入環形緩沖區)。
    • 重新啟動 DMA 接收(調用 HAL_UARTEx_ReceiveToIdle_DMA)。
  6. 主循環處理數據:調用 uart_proc,從環形緩沖區中提取數據并處理

6. 圖文總結

UART RX --> DMA 接收數據 --> RX 空閑中斷 --> USART1_IRQHandler --> HAL_UARTEx_RxEventCallback|                                     ||---- 重新啟動 DMA 接收 ----------------|
數據 --> 寫入環形緩沖區 --> 主循環讀取數據 --> 用戶處理

本系統實現了 STM32 串口 DMA 接收 + 空閑中斷 + 環形緩沖區,旨在高效接收和處理串口不定長數據,保證數據的完整性與實時性。其核心工作流程如下:

  1. DMA 接收:通過調用 HAL_UARTEx_ReceiveToIdle_DMA 函數啟動 DMA 模式接收,將接收到的數據自動存儲到 DMA 緩沖區,減少 CPU 干預,提高效率。
  2. 空閑中斷觸發:當串口 RX 線超過一個字節時間沒有新數據輸入時,觸發 空閑中斷(IDLE),并在中斷中調用 HAL_UART_IRQHandler,進一步觸發 HAL_UARTEx_RxEventCallback 回調函數。
  3. 數據存儲
    在回調函數 HAL_UARTEx_RxEventCallback 中,將 DMA 緩沖區接收到的數據寫入 環形緩沖區,通過 ringbuffer_write 函數實現數據的安全存儲,防止數據丟失。隨后清空 DMA 緩沖區,重新啟動 DMA 接收,確保數據連續接收。
  4. 數據處理
    在主循環中,調用 uart_proc 函數,通過 ringbuffer_read 從環形緩沖區讀取數據進行處理。環形緩沖區通過讀寫指針和數據計數機制實現數據的循環存儲與讀取,適用于不定長、連續數據接收的場景。
  5. 環形緩沖區管理
    • ringbuffer_is_fullringbuffer_is_empty 用于判斷緩沖區狀態。
    • ringbuffer_writeringbuffer_read 分別實現數據的寫入與讀取,確保緩沖區數據有序管理,防止數據丟失。

系統特點

  • 高效性:DMA 自動接收數據,減少 CPU 開銷。
  • 實時性:通過 UART 空閑中斷實時捕獲數據接收完成狀態。
  • 可靠性:使用環形緩沖區管理數據,確保數據存儲穩定,避免數據丟失。
  • 適用性:適合高頻率、不定長數據的串口通信場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895435.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895435.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895435.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

股指期貨是什么?股指期貨日內拐點有什么特征?

股指期貨是一種金融衍生品,股指期貨日內拐點就是在一天交易過程中,市場走勢發生顯著改變的那個點。 股指期貨是什么? 股指是一個指數,比如上證50指數、滬深300指數、中證500指數以及中證1000指數,這是一堆股票的一個整…

Opensearch/ElasticSearch-ctx查詢內容不全的問題

問題 在OpenSearch中,我希望在action中把一整條log作為報警內容發送出來,但是根據文檔,配置為ctx.results.0.hits.hits.0._source.log,但是發現根本找不到這個值 經過查詢,我發現在返回的ctx中僅存在如下的值 resul…

vue2和vue3插槽slot最通俗易懂的區別理解

在 Vue 的組件通信中,slot(插槽)的編譯優化是一個重要的性能提升點。以下是 Vue2 和 Vue3 在 slot 處理上的差異及優化原理,用更直觀的方式解釋: Vue2 的 Slot 更新機制 想象一個父子組件場景: 父組件&am…

【16屆藍橋杯寒假刷題營】第1期DAY4

1.披薩和西藍花 - 藍橋云課 1. 披薩和西藍花 問題描述 在接下來的 N 天里(編號從 1 到 N),坤坤計劃烹飪披薩或西蘭花。他寫下一個長度為 N 的字符串 A,對于每個有效的 i,如果字符 Ai 是 1,那么他將在第 i…

你需要了解的遠程登錄協議——Telnet

你需要了解的遠程登錄協議——Telnet 一. 什么是Telnet?二. Telnet的優缺點三. Telnet vs SSH:哪一個更適合?四. Telnet的應用場景 前言 點個免費的贊和關注,有錯誤的地方請指出,看個人主頁有驚喜。 作者:神…

本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui

通過ollama本地部署deepseek 總共兩步 1.模型部署 2.[web頁面] 參考官網 ollama:模型部署 https://ollama.com/ open-webui:web頁面 https://github.com/open-webui/open-webui 設備參考 Mac M 芯片 windows未知 蒸餾模型版本:deepseek-r1:14b 運行情況macminim2 24256 本地…

PHP在線題庫小程序

📚 在線題庫小程序:學習提分新神器,輕松躍升學霸行列 這是一款專為追夢學子精心策劃、基于ThinkPHPUniApp框架匠心打造的在線題庫類微信小程序系統。它宛如一把?智慧鑰匙?,為追求高效學習的你解鎖🔓知識寶庫的大門。…

Java開發中的連接池技術介紹

連接池技術是Java開發中用于管理數據庫連接的重要技術,尤其在SSM(Spring、Spring MVC、MyBatis)架構中,連接池能夠顯著提升數據庫操作的性能和資源利用率。下面我們將詳細介紹連接池技術解決的問題、配置方案以及代碼實現。 1. 連…

Unity-Mirror網絡框架-從入門到精通之Pong示例

文章目錄 前言示例介紹NetworkManagerPongBallPlayer總結前言 在現代游戲開發中,網絡功能日益成為提升游戲體驗的關鍵組成部分。本系列文章將為讀者提供對Mirror網絡框架的深入了解,涵蓋從基礎到高級的多個主題。Mirror是一個用于Unity的開源網絡框架,專為多人游戲開發設計…

布隆過濾器到底是什么東西?它有什么用

布隆過濾器:用概率換空間的奇妙數據結構 引言:當空間成為奢侈品 在互聯網每天產生2.5萬億字節數據的時代,Google每秒處理超過9萬次搜索請求,Redis緩存系統支撐著百萬級QPS的訪問。面對如此海量的數據處理需求,傳統的…

任務1 將單表中的單個rfid增加為多個rfid

方案 使用連表查詢解決 單獨創建一個rfid的表 讓tool_id對應多個rfid 需要優化的表 1:tool_materials_stock 庫存管理 已完成 數據遷移完成 原庫rfid字段未刪除 2:tool_borrow_return 借出借還管理 已完成 3:too…

OutSystems Platform Tools Platform Services

概述(Overview) outsystems是一整套低代碼的企業級應用(WEB 和 移動端)的開發環境。 本文主要講解outsystems的Platform Tools與Platform Services 平臺工具(Platform Tools) 集成開發環境IDE&#xff0…

【深度解析】ETERM指令:離港系統的核心技術

在民航離港系統中,ETERM(中航信終端模擬系統)是廣泛使用的指令操作系統,主要用于航班控制、旅客值機、登機等操作。以下是一些核心的ETERM指令及其功能分類: 1. 航班信息查詢與操作 FLR:顯示航班列表&…

ES的java操作

ES的java操作 一、添加依賴 在pom文件中添加依賴包 <dependencies><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</version></dependency><!-- elastic…

DeepSeek 從入門到精通學習指南,2025清華大學《DeepSeek從入門到精通》正式發布104頁pdf版超全解析

DeepSeek 是一款強大的 AI 搜索引擎&#xff0c;廣泛應用于企業級數據檢索和分析。無論您是初學者還是有經驗的用戶&#xff0c;掌握 DeepSeek 的使用都能為您的工作帶來極大的便利。本文將從入門到精通&#xff0c;詳細介紹如何學習和使用 DeepSeek。 鏈接: https://pan.baid…

飛書專欄-TEE文檔

CSDN學院課程連接&#xff1a;https://edu.csdn.net/course/detail/39573

2025.2.11——一、[極客大挑戰 2019]PHP wakeup繞過|備份文件|代碼審計

題目來源&#xff1a;BUUCTF [極客大挑戰 2019]PHP 目錄 一、打開靶機&#xff0c;整理信息 二、解題思路 step 1&#xff1a;目錄掃描、爆破 step 2&#xff1a;代碼審計 1.index.php 2.class.php 3.flag.php step 3&#xff1a;繞過__wakeup重置 ?編輯 三、小結…

AI大模型(DeepSeek)科研應用、論文寫作、數據分析與AI繪圖學習

【介紹】 在人工智能浪潮中&#xff0c;2024年12月中國公司研發的 DeepSeek 橫空出世以驚艷全球的姿態&#xff0c;成為 AI領域不可忽視的力量!DeepSeek 完全開源&#xff0c;可本地部署&#xff0c;無使用限制&#xff0c;保護用戶隱私。其次&#xff0c;其性能強大&#xff…

考研操作系統----操作系統的概念定義功能和目標(僅僅作為王道嗶站課程講義作用)

目錄 操作系統的概念定義功能和目標 操作系統的四個特征 操作系統的分類 ?編輯 操作系統的運行機制 系統調用 操作系統體系結構 操作系統引導 虛擬機 操作系統的概念定義功能和目標 什么是操作系統&#xff1a; 操作系統是指控制和管理整個計算機系統的軟硬件資源&…

DeepSeek 突然來襲,AI 大模型變革的危機與轉機藏在哪?

隨著人工智能技術的飛速發展&#xff0c;大模型領域不斷涌現出具有創新性的成果。DeepSeek 的橫空出世&#xff0c;為 AI 大模型領域帶來了新的變革浪潮。本文將深入探討 DeepSeek 出現后 AI 大模型面臨的危機與轉機。 沖沖沖&#xff01;&#xff01;&#xff01; 目錄 一、…