[STM32 HAL庫]串口中斷編程思路

一、前言

最近在準備藍橋杯比賽(嵌入式賽道),研究了以下串口空閑中斷+DMA接收不定長的數據,感覺這個方法的接收效率很高,十分好用。方法配置都成功了,但是有一個點需要進行考慮,就是一般我們需要對串口接收的數據進行處理,這個數據處理是在中斷的回調函數里面處理還是在主函數里面處理好呢?以下就這兩個方法進行分析:

二、方法分析

目前我想到的有兩種方法:

方法一

在回調函數里直接處理數據

優點:

  • 實時性強:數據接收完成后立即處理,減少了數據處理的延遲。
  • 代碼簡潔:數據接收和處理邏輯在同一個地方,代碼易于理解和維護。

缺點:

  • 占用中斷處理時間:如果數據處理邏輯復雜或耗時,會影響中斷的響應速度,進而影響系統其他功能的實時性。
  • 可維護性差:如果數據處理邏輯復雜,中斷處理函數會變得冗長,難以維護。

方法二

在回調函數中設置標志位,在主函數里讀取標志位再進行數據處理

優點:

  • 保護中斷響應速度:中斷處理函數只負責設置標志位,數據處理在主循環中進行,保證了中斷的響應速度。
  • 代碼結構清晰:中斷處理函數和數據處理邏輯分離,代碼結構更清晰,易于維護和擴展。
  • 資源利用率高:可以在主循環中根據系統狀態靈活調度數據處理,避免在中斷中處理復雜邏輯造成的資源浪費。

缺點:

  • 增加了一定的復雜性:需要額外管理標志位,以及同步數據接收和處理的邏輯。
  • 可能引入延遲:數據處理被推遲到主循環中進行,可能會引入一定的處理延遲。

總結

  • 數據處理的復雜度:如果數據處理邏輯復雜或耗時,建議采用方法二,以保護中斷響應速度。
  • 系統的實時性要求:如果系統對實時性要求較高,且數據處理不是非常耗時,方法一可能更合適。但如果數據處理可能影響到系統的其他實時功能,方法二則更為穩妥。
  • 代碼的可維護性和擴展性:如果希望代碼結構更清晰,易于維護和擴展,方法二通常是更好的選擇。

三、實際操作

配置的方法可以看之前寫的文章
鏈接: [STM32 HAL庫]串口空閑中斷+DMA接收不定長數據

實驗現象:將電腦發來的數據,原封不到的發送回去。特別注意BUFF_SIZE的大小,太小會造成接收數據的丟失。

方法一

在這個方法中,在中斷的回調函數里直接發送回去數據,并手動開啟下一次的中斷。

#define BUFF_SIZE	128
uint8_t rx_buffer[BUFF_SIZE];  // 創建接收緩存,大小為BUF_SIZE
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手動開啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);	//手動關閉DMA_IT_HT中斷	while (1){}
}
void SystemClock_Config(void)
{//...
}
/* 串口接收完成回調函數 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if (huart->Instance == USART1){HAL_UART_Transmit(&huart1, rx_buffer, Size, 0xffff);// 將接收到的數據再發出HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE); // 接收完畢后重啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手動關閉DMA_IT_HT中斷memset(rx_buffer, 0, BUFF_SIZE);// 清除接收緩存	}
}
/* 串口錯誤回調函數 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef * huart)
{if(huart->Instance == USART1){HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE); // 接收完畢后重啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手動關閉DMA_IT_HT中斷memset(rx_buffer, 0, BUFF_SIZE);// 清除接收緩存}
}

方法二

在這個方法中,在串口接收完成的回調函數置接收完成的標志位,然后在主函數中進行判斷。判斷成立則進行數據的發送,并手動開啟下一次的中斷和清除標志位。

需要注意的是,不要在回調函數里面手動開啟下一次的中斷,因為有可能會出現主函數數據還未處理完成,下一個串口數據就到來而覆蓋上一次的串口數據。
所以,這里程序的處理方法是:程序處理完本次數據,則開啟下一次中斷接收;程序未處理完本次數據,則不開啟下一次中斷接收

#define BUFF_SIZE	128
uint8_t rx_buffer[BUFF_SIZE];  	// 創建接收緩存,大小為BUF_SIZE
_Bool 	u1_rx_end_flag = 0;		//USART1接收數據完成標志位 1:接收完成
uint16_t u1_rx_size;			//USART1接收數據實際長度
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手動開啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);		   	//手動關閉DMA_IT_HT中斷	while (1){/* 判斷接收是否完成 */if(u1_rx_end_flag == 1){/* 對接收的數據進行處理 */HAL_UART_Transmit(&huart1, rx_buffer, u1_rx_size, 0xffff);// 將接收到的數據再發出memset(rx_buffer, 0, BUFF_SIZE);	// 清除接收緩存/* 開啟下一次中斷 */HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手動開啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);//手動關閉DMA_IT_HT中斷	/* 清除標志位 */u1_rx_end_flag = 0;}}
void SystemClock_Config(void)
{//...
}
/* 串口接收完成回調函數 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if (huart->Instance == USART1){u1_rx_end_flag = 1;	//置標志位u1_rx_size = Size;		//獲取接收數據長度}
}	
/* 串口錯誤回調函數 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef * huart)
{if(huart->Instance == USART1){HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE);//手動開啟串口DMA模式接收數據__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手動關閉DMA_IT_HT中斷memset(rx_buffer, 0, BUFF_SIZE);// 清除接收緩存}
}

值得一提的是,若是沒有手動開啟串口空閑中斷,那么串口錯誤中斷也不會被開啟,也就無法進入串口錯誤回調函數

四、實驗現象

兩個方法實現現象一致
在這里插入圖片描述

應該還有更好的串口接收模式,現在來說,這個方法應該夠用了。

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

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

相關文章

淺談Java之AJAX

一、基本介紹 在Java開發中,AJAX(Asynchronous JavaScript and XML)是一種用于創建動態網頁的技術,它允許網頁在不重新加載整個頁面的情況下與服務器進行交互。 二、關鍵點和示例 1. AJAX的基本原理 AJAX通過JavaScript的XMLHtt…

AutoSar架構學習筆記

1.AUTOSAR(Automotive Open System Architecture,汽車開放系統架構)是一個針對汽車行業的軟件架構標準,旨在提升汽車電子系統的模塊化、可擴展性、可重用性和互操作性。AUTOSAR的目標是為汽車電子控制單元(ECU&#xf…

算法競賽之差分進階——等差數列差分 python

目錄 前置知識進入正題實戰演練 前置知識 給定區間 [ l, r ],讓我們把數組中的[ l, r ] 區間中的每一個數加上c,即 a[ l ] c , a[ l 1 ] c , a[ l 2] c , a[ r ] c; 怎么做?很簡單,差分一下即可 還不會的小伙伴點此進入學習 進入正題 …

TDengine 做 Apache SuperSet 數據源

?Apache Superset? 是一個現代的企業級商業智能(BI)Web 應用程序,主要用于數據探索和可視化。它由 Apache 軟件基金會支持,是一個開源項目,它擁有活躍的社區和豐富的生態系統。Apache Superset 提供了直觀的用戶界面…

金融場景 PB 級大規模日志平臺:中信銀行信用卡中心從 Elasticsearch 到 Apache Doris 的先進實踐

導讀:中信銀行信用卡中心每日新增日志數據 140 億條(80TB),全量歸檔日志量超 40PB,早期基于 Elasticsearch 構建的日志云平臺,面臨存儲成本高、實時寫入性能差、文本檢索慢以及日志分析能力不足等問題。因此…

虛幻商城 Fab 免費資產自動化入庫

文章目錄 一、背景二、實現效果展示三、實現自動化入庫一、背景 上一次寫了個這篇文章 虛幻商城 Quixel 免費資產一鍵入庫,根據這個構想,便決定將范圍擴大,使 Fab 商城的所有的免費資產自動化入庫,是所有!所有! 上一篇文章是根據下圖這部分資產一鍵入庫: 而這篇文章則…

游戲為什么失敗?回顧某平庸游戲

1、上周玩了一個老鼠為主角的游戲,某平臺喜1送的, 下載了很久而一直沒空玩,大約1G,為了清硬盤空間而玩。 也是為了拔掉心中的一根刺,下載了而老是不玩總感覺不舒服。 2、老鼠造型比較寫實,看上去就有些討…

親測有效!如何快速實現 PostgreSQL 數據遷移到 時序數據庫TDengine

小T導讀:本篇文章是“2024,我想和 TDengine 談談”征文活動的優秀投稿之一,作者從數據庫運維的角度出發,分享了利用 TDengine Cloud 提供的遷移工具,從 PostgreSQL 數據庫到 TDengine 進行數據遷移的完整實踐過程。文章…

C#,入門教程(01)—— Visual Studio 2022 免費安裝的詳細圖文與動畫教程

通過本課程的學習,你可以掌握C#編程的重點,享受編程的樂趣。 在本課程之前,你無需具備任何C#的基礎知識,只要能操作電腦即可。 不過,希望你的數學不是體育老師教的。好的程序是數理化的實現與模擬。沒有較好的數學基礎…

Linux探秘坊-------3.開發工具詳解(2)

1.動靜態庫和動靜態鏈接(操作) 靜態庫是指編譯鏈接時,把庫?件的代碼全部加?到可執??件中,因此?成的?件 ?較?,但在運?時也就不再需要庫?件了。其后綴名?般為“.a” 動態庫與之相反,在編譯鏈接時并 沒有把庫?件的代碼加?到可執??件中 ,?…

電腦開機出現Bitlock怎么辦

目錄 1.前言 2.產生原因: 1.系統異常關機 2.系統更新錯誤 3.硬件更換 4.CMOS電池問題 5.出廠設置 6.意外情況 3.解鎖步驟: 3.1:記住密鑰ID(前6位) 3.2:打開aka.ms/myrecoverykey網址 3.3&#…

C# 的 NLog 庫高級進階

一、引言 在 C# 開發的廣袤天地中,日志記錄宛如開發者的 “千里眼” 與 “順風耳”,助力我們洞察應用程序的運行狀態,快速定位并解決問題。而 NLog 庫,無疑是日志記錄領域中的璀璨明星,以其強大的功能、靈活的配置和出…

Avalonia系列文章之小試牛刀

最近有朋友反饋,能否分享一下Avalonia相關的文章,于是就抽空學習了一下,發現Avalonia真的是一款非常不錯的UI框架,值得花時間認真學習一下,于是邊學習邊記錄,整理成文,分享給大家,希…

10 為什么系統需要引入分布式、微服務架構

java技術的發展 在java開始流行起來之后,主要服務于企業家應用,例如ERP,CRM等等,這些項目是為企業內部員工使用,我們的思維是怎么用設計模式,如何封裝代碼。讓開發人員關注到業務上去,系統也就那么幾十幾百…

第6章:Python TDD實例變量私有化探索

寫在前面 這本書是我們老板推薦過的,我在《價值心法》的推薦書單里也看到了它。用了一段時間 Cursor 軟件后,我突然思考,對于測試開發工程師來說,什么才更有價值呢?如何讓 AI 工具更好地輔助自己寫代碼,或許…

JDK 23 和 JDK 21 的區別

JDK 23 和 JDK 21 的區別主要在于支持周期和功能特性: 支持周期: JDK 23:此版本是一個常規發布版本,支持時間較短,通常是六個月。這種版本適合希望使用最新特性和改進的用戶。JDK 21:這是一個長期支持&…

springboot自動配置原理(高低版本比較)spring.factories文件的作用

SpringBootApplication public class SpringSecurityApplication {public static void main(String[] args) {SpringApplication.run(SpringSecurityApplication.class, args);}}注解SpringBootApplication Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Doc…

使用Websocket進行前后端實時通信

1、引入jar&#xff0c;spring-websocket-starter <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency> 2、配置websocket config import org.springframe…

vue2 - Day05 - VueX

Vuex 是 Vue.js 官方的狀態管理庫。它是一個讓你能在應用中集中管理共享狀態的工具。當應用的規模逐漸增大&#xff0c;組件之間的數據傳遞變得越來越復雜時&#xff0c;Vuex 就成為了救星&#xff0c;提供了一個集中式的存儲來管理所有的組件狀態&#xff0c;并且保證狀態以一…

中型項目中 HTTP 的挑戰與解決方案

一、引言 在當今數字化時代&#xff0c;HTTP&#xff08;超文本傳輸協議&#xff09;作為Web應用程序的基礎通信協議&#xff0c;在中型項目的開發中扮演著至關重要的角色。它為客戶端和服務器之間的數據傳輸提供了標準規范&#xff0c;使得各種類型的應用&#xff0c;從簡單的…