單片機裸機程序設計架構

文章目錄

      • 一、前后臺系統(Foreground-Background System)
      • 二、時間片輪詢架構(Time-Slicing Polling)
      • 三、狀態機架構(State Machine)
      • 四、事件驅動架構(Event-Driven)
      • 五、架構設計原則
      • 總結

單片機裸機程序(無操作系統的單片機程序)的架構設計直接影響程序的
可靠性、可維護性和擴展性。由于單片機資源有限(內存、算力、外設等),裸機架構需遵循“簡潔高效、任務可控”的原則,常見架構主要有以下幾種:

一、前后臺系統(Foreground-Background System)

最基礎、最常用的架構,適合任務簡單、實時性要求不高的場景。

  • 前臺(Foreground):由中斷服務程序(ISR)組成,負責處理緊急事件(如外部觸發、定時器溢出、數據接收等),優先級最高,執行時間需盡可能短(避免阻塞其他中斷)。
  • 后臺(Background):即主循環(main loop),負責處理非緊急的常規任務(如數據處理、狀態刷新、外設控制等),按順序循環執行。
  • 協作方式:前臺通過設置標志位(flag)通知后臺處理任務,后臺在主循環中輪詢標志位,觸發對應處理邏輯。

示例流程

// 全局標志位(前臺通知后臺的“信號”)
uint8_t uart_rx_flag = 0;  // 串口接收完成標志
uint8_t key_press_flag = 0; // 按鍵按下標志int main(void) {// 初始化:外設、中斷、全局變量等init_uart();init_key();init_led();while(1) {  // 后臺主循環if(uart_rx_flag) {uart_rx_flag = 0;process_uart_data();  // 處理串口數據(非緊急)}if(key_press_flag) {key_press_flag = 0;handle_key_event();   // 處理按鍵事件(非緊急)}update_led_status();      // 周期性刷新LED(常規任務)}
}// 串口接收中斷服務程序(前臺)
void UART_IRQHandler(void) {if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {uart_rx_buf = USART_ReceiveData(USART1);uart_rx_flag = 1;  // 設置標志位,通知后臺處理USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

優點:結構簡單,資源占用少,易于實現。
缺點:后臺任務按順序執行,若某個任務耗時過長,會阻塞后續任務,實時性差。

二、時間片輪詢架構(Time-Slicing Polling)

適合多任務周期性執行的場景(如工業控制、傳感器采集),通過定時器劃分“時間片”,按固定周期輪流執行任務。

  • 核心思想:用定時器(如SysTick)產生固定間隔的中斷(如1ms),在中斷中更新“系統時基”,并為每個任務分配“時間片”(執行周期)。
  • 任務調度:主循環中輪詢所有任務,若任務的“時間片到期”(當前時基達到任務周期),則執行該任務,執行完成后等待下一個周期。
    提示:下面代碼中有Bug: ------- sys_tick 溢出就不準拉
    示例流程
// 任務結構體:包含周期、上次執行時間、處理函數
typedef struct {uint32_t period;       // 任務周期(ms)uint32_t last_run;     // 上次執行時間(時基)void (*func)(void);    // 任務處理函數
} TaskType;// 系統時基(由定時器中斷更新)
uint32_t sys_tick = 0;// 任務列表
TaskType tasks[] = {{10, 0, task_sensor_read},  // 10ms讀取一次傳感器{100, 0, task_data_report}, // 100ms上報一次數據{500, 0, task_led_flash},   // 500ms閃爍一次LED
};
#define TASK_NUM (sizeof(tasks)/sizeof(TaskType))// 定時器中斷(1ms觸發一次,更新時基)
void SysTick_Handler(void) {sys_tick++;
}int main(void) {init_sys();SysTick_Config(SystemCoreClock / 1000);  // 配置1ms時基while(1) {for(int i=0; i<TASK_NUM; i++) {// 檢查任務是否到執行時間if(sys_tick - tasks[i].last_run >= tasks[i].period) {tasks[i].last_run = sys_tick;  // 更新上次執行時間tasks[i].func();               // 執行任務}}}
}// 任務實現示例
void task_sensor_read(void) {// 讀取溫濕度傳感器...
}

優點:任務執行周期可控,避免單任務阻塞,適合周期性任務。
缺點:任務仍在主循環中執行,若某任務執行時間超過其周期,會影響后續任務;無優先級區分,實時性中等。

三、狀態機架構(State Machine)

適合邏輯復雜、狀態多變的單任務場景(如設備啟停流程、人機交互),將任務分解為“狀態”,通過條件判斷切換狀態,避免嵌套邏輯混亂。

  • 核心思想:將任務劃分為多個“狀態”(如初始化、運行、暫停、故障),每個狀態對應特定的處理邏輯,通過“狀態變量”記錄當前狀態,在主循環中根據輸入(事件)切換狀態。
  • 分類
    • 單狀態機:單個任務的狀態管理(如一個傳感器的工作流程);
    • 層次狀態機(HSM):復雜任務的狀態嵌套(如主狀態包含子狀態)。

示例流程

// 定義狀態枚舉
typedef enum {DEVICE_INIT,    // 初始化狀態DEVICE_RUN,     // 運行狀態DEVICE_PAUSE,   // 暫停狀態DEVICE_ERROR    // 錯誤狀態
} DeviceState;DeviceState current_state = DEVICE_INIT;  // 當前狀態
uint8_t error_flag = 0;                   // 錯誤標志(觸發狀態切換)int main(void) {while(1) {switch(current_state) {case DEVICE_INIT:if(init_success()) {  // 初始化成功current_state = DEVICE_RUN;start_device();} else {current_state = DEVICE_ERROR;  // 初始化失敗}break;case DEVICE_RUN:if(error_flag) {current_state = DEVICE_ERROR;  // 運行中出錯error_flag = 0;} else if(key_pause_pressed()) {current_state = DEVICE_PAUSE;  // 暫停按鍵觸發} else {run_task();  // 執行運行狀態的邏輯}break;case DEVICE_PAUSE:if(key_resume_pressed()) {current_state = DEVICE_RUN;  // 恢復運行}break;case DEVICE_ERROR:handle_error();  // 錯誤處理(如報警、重啟)break;}}
}

優點:邏輯清晰,避免深層嵌套(if-else/switch-case),易于調試和擴展。
缺點:主要適用于單任務,多任務需結合其他架構(如時間片)。

四、事件驅動架構(Event-Driven)

適合多外部事件響應的場景(如按鍵、通信、傳感器觸發),基于“事件”觸發任務,而非輪詢,提高CPU效率。

  • 核心思想:定義“事件”(如按鍵按下、數據接收、超時等),每個事件關聯對應的“回調函數”;通過中斷或輪詢檢測事件,觸發回調執行。
  • 實現方式:用事件隊列(FIFO)存儲事件,主循環不斷從隊列中取出事件并分發處理,支持事件優先級。

示例流程

// 事件類型定義
typedef enum {EVENT_KEY_PRESS,    // 按鍵事件EVENT_UART_RX,      // 串口接收事件EVENT_TIMEOUT       // 超時事件
} EventType;// 事件結構體
typedef struct {EventType type;     // 事件類型void* data;         // 事件附加數據(如按鍵值、接收數據)
} Event;// 事件隊列(FIFO)
#define EVENT_QUEUE_SIZE 10
Event event_queue[EVENT_QUEUE_SIZE];
uint8_t queue_head = 0, queue_tail = 0;// 入隊事件
void event_enqueue(Event event) {uint8_t next_tail = (queue_tail + 1) % EVENT_QUEUE_SIZE;if(next_tail != queue_head) {  // 隊列未滿event_queue[queue_tail] = event;queue_tail = next_tail;}
}// 主循環:事件分發
int main(void) {init_periph();  // 初始化外設和中斷while(1) {if(queue_head != queue_tail) {  // 隊列非空Event event = event_queue[queue_head];queue_head = (queue_head + 1) % EVENT_QUEUE_SIZE;  // 出隊// 分發事件到對應處理函數switch(event.type) {case EVENT_KEY_PRESS:handle_key((uint8_t*)event.data);break;case EVENT_UART_RX:handle_uart((uint8_t*)event.data);break;case EVENT_TIMEOUT:handle_timeout();break;}}}
}// 按鍵中斷:觸發事件入隊
void KEY_IRQHandler(void) {Event event;event.type = EVENT_KEY_PRESS;event.data = (void*)get_key_value();  // 獲取按鍵值event_enqueue(event);  // 事件入隊
}

優點:CPU利用率高(無輪詢空耗),事件響應靈活,支持多事件并行處理。
缺點:需實現事件隊列和分發邏輯,復雜度高于前后臺系統。

五、架構設計原則

  1. 模塊化:按功能拆分模塊(如uart.c、key.c、sensor.c),模塊間通過接口通信,降低耦合。
  2. 資源管理:明確外設(GPIO、定時器、DMA)的歸屬,避免沖突(如用“資源鎖”保護共享外設)。
  3. 中斷管理:中斷僅做“最短處理”(如置標志、存數據),復雜邏輯放后臺;合理設置中斷優先級,避免嵌套過深。
  4. 可擴展性:預留接口(如任務注冊、事件類型),方便后期增加功能。
  5. 健壯性:處理邊界情況(如隊列滿、數據溢出、超時),避免程序崩潰。

總結

  • 簡單場景(如LED控制、單傳感器采集):優先用前后臺系統
  • 多周期性任務(如定時采集+上報):用時間片輪詢
  • 復雜邏輯任務(如設備狀態切換):用狀態機
  • 多事件響應(如多按鍵+多通信):用事件驅動

實際開發中,常結合多種架構(如“時間片+狀態機”“事件驅動+前后臺”),以適應具體需求。

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

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

相關文章

odoo-061 PostgreSQL 中處理 NULL 值的 SQL 條件寫法

文章目錄1. 檢查是否為 NULL2. NULL 值與比較運算符3. 在聚合函數中處理 NULL4. 在 WHERE 子句中的復雜條件注意事項在 PostgreSQL 中處理 NULL 值需要特別注意&#xff0c;因為 NULL 表示"未知"或"不存在"的值&#xff0c;與普通值的行為不同。以下是幾種…

Flink CDC 介紹

一、什么是 CDCCDC 是 Change Data Capture(變更數據獲取)的簡稱。核心思想是&#xff0c;監測并捕獲數據庫的變動&#xff08;包括數據或數據表的插入、更新以及刪除等&#xff09;&#xff0c;將這些變更按發生的順序完整記錄下來&#xff0c;寫入到消息中間件中以供其他服務…

暑期第三周(7.28-8.3)

其實 web [SWPUCTF 2021 新生賽]easy_sql 開啟環境后看到一個提示“球球你輸入點東西吧&#xff01;”沒有其他信息&#xff0c;就看看源碼 直接試試get傳參 有所顯示 看看是字符型還是數字型 可以判定是字符型 接下來判斷閉合類型 根據顯示&#xff0c;可以得知是單引…

【物聯網】基于樹莓派的物聯網開發【21】——MQTT獲取樹莓派傳感器數據廣播實戰

場景介紹 今天程序貓帶領大家如何獲取樹莓派傳感器溫濕度數據&#xff0c;并用MQTT進行廣播。 實現過程 啟動MQTT服務 1、終端啟動Mosquitto服務 sudo systemctl start mosquitto 2、設置服務開機自動啟動 sudo systemctl enable mosquitto硬件連接 樹莓派4b連接GPIO引腳與DHT1…

Mysql自定義順序查詢

1、使用函數MySQL 的 ORDER BY FIELD() 函數可以按照指定的自定義順序對查詢結果進行排序&#xff0c;而不是默認的升序&#xff08;ASC&#xff09;或降序&#xff08;DESC&#xff09;。2、適用場景后端/運營人員經常需要臨時把某幾條記錄‘拽’到最前&#xff08;或最后&…

回歸預測 | MATLAB實現RBF徑向基神經網絡多輸入單輸出回歸預測+SHAP可解釋分析

目錄 基于RBF徑向基神經網絡多輸入單輸出回歸預測及SHAP可解釋分析的研究 摘要 1. 引言 1.1 研究背景 1.2 研究意義 1.3 研究目標與內容 2. 文獻綜述 2.1 RBF徑向基神經網絡研究現狀 2.2 SHAP可解釋分析研究進展 3. RBF徑向基神經網絡原理 4. SHAP可解釋分析理論基礎 4.1 Shapl…

--- Eureka 服務注冊發現 ---

Euraka 是netfix開發的基于REST服務基于AP框架的注冊中心&#xff0c;主要是用于服務的注冊&#xff0c;管理&#xff0c;負載均衡&#xff0c;服務故障轉移 Eureka主要分倆部分Eureka Server&#xff1a;服務中心Server端&#xff0c;提供服務注冊 發現 健康檢查等服務Eureka …

vue3 el-select 加載內容后 觸發事件

在 Vue 3 中使用 Element UI 的 el-select 組件實現加載內容后觸發事件&#xff0c;主要有以下兩種常見需求及實現方式&#xff1a;加載數據后觸發事件若需在數據加載完成后觸發特定事件&#xff08;如頁面渲染完成&#xff09;&#xff0c;可通過自定義指令監聽滾動容器狀態&a…

c# winform 調用 海康威視工業相機(又全又細又簡潔)

1.準備一個海康相機 從垃圾桶里翻出來一個USB口相機。 2.下載MVS 和SDK 海康機器人-機器視覺-下載中心 mvs&#xff1a; sdk&#xff1a; 用MVS 調試一下&#xff0c;能連接就行。 海康威視相機&#xff0c;MVS連接成功&#xff0c;但無圖像怎么辦&#xff1f;-CSDN博客 3.打…

前端頁面直接生成PDF下載文件

前言 因為要實現業務需求如下圖&#xff0c;業務邏輯&#xff0c;該憑證為前端代碼實現&#xff0c;為了簡單方便實現下載為pdf的需求。 一、怎么在前端直接生成PDF&#xff1f; 需求描述&#xff1a;瀏覽器打開的這個頁面&#xff0c;點擊下載&#xff0c;把當前彈框頁面的…

性能優化——GPU的影響

關閉MSAA 之前在查一個渲染問題&#xff0c;一開始是定位到了CPU在waitforFrame所以知道是GPU的問題但如何定義GPU的問題在哪里&#xff0c;就很麻煩。我一開始以為是drawcall的問題&#xff0c;因為我發現drawcall有350個但降低到30個后&#xff0c;依然情況沒有好轉。畢竟dra…

軟件需求關閉前的質量評估標準是什么

在 需求關閉前&#xff0c;進行 質量評估 是確保需求被完整實現、測試充分且滿足業務目標的關鍵步驟。以下是需求關閉前的質量評估標準&#xff0c;涵蓋了功能、非功能、測試覆蓋率和用戶滿意度等方面&#xff1a;一、功能實現的質量評估標準需求完整性&#xff1a;所有功能需求…

vscode中創建python虛擬環境的方法

文章目錄框架不同python解釋器vscode運行python需要的插件vscode可以改變執行python腳本的默認終端虛擬環境解釋創建虛擬環境的方法python的settings.json的一些好用配置框架 python解釋器->虛擬環境->vscode 不同python解釋器 在一臺電腦中我們可以安裝多個版本的pyt…

基于 ShardingSphere 的 Spring Boot 數據加密與模糊查詢實現

基于 ShardingSphere 的 Spring Boot 數據加密與模糊查詢實現 在數據安全與查詢便捷性并重的今天,敏感數據加密存儲后如何支持靈活查詢成為關鍵挑戰。本文將聚焦ShardingSphere 在實現數據加密的同時支持模糊查詢的核心能力,詳細介紹基于 Spring Boot 和 ShardingSphere 的完…

計算虛擬化技術

&#x1f9e0; 一、什么是計算虛擬化&#xff1f;&#xff08;基礎認識&#xff09; ? 基本概念&#xff1a; 計算虛擬化&#xff08;Compute Virtualization&#xff09; 是指&#xff1a;在一臺物理服務器上模擬多個“虛擬計算資源”&#xff0c;每個虛擬機看起來像是一臺獨…

Python編程基礎與實踐:Python基礎數據結構:列表、字典和集合

Python數據結構&#xff1a;掌握列表、字典和集合 學習目標 通過本課程的學習&#xff0c;學員將掌握Python中基本的數據結構&#xff1a;列表、字典和集合。學員將了解它們的特性、使用場景以及如何高效地使用它們來解決實際問題。 相關知識點 列表、字典和集合使用 學習…

三維偏序 -- cdq 套 cdq

似乎題解區并沒有 cdq 套 cdq 的作法&#xff0c;剛好今天講了&#xff0c;就來寫一發。 題意與記號 題目講的很清楚了。此方法并沒有樹狀數組好想也沒有其高效&#xff0c;但能很方便擴展。下文記原序列為 ddd&#xff0c;將每個點拆分成點與詢問&#xff0c;內部增加一個名為…

Effective C++ 條款27: 盡量用const、enum、inline替換 #define

Effective C 條款27&#xff1a;盡量用const、enum、inline替換#define核心思想&#xff1a;使用編譯器&#xff08;const, enum, inline&#xff09;替代預處理器&#xff08;#define&#xff09;&#xff0c;讓編譯器進行語義檢查&#xff0c;避免宏替換引發的錯誤和調試困難…

芯谷科技--高效噪聲降低解決方案壓縮擴展器D5015

在無繩電話系統中&#xff0c;噪聲降低是提升通話質量的關鍵。 D5015 壓縮擴展器&#xff0c;通過集成壓縮器和擴展器&#xff0c;有效降低了傳輸噪聲&#xff0c;同時保持了信號的完整性。D5015 采用 SOP20 和 DIP20 封裝形式&#xff0c;具有低電壓工作、低功耗、高集成度等特…

LabVIEW車床靜剛度自動測

?基于LabVIEW 平臺開發車床靜剛度自動測試系統&#xff0c;針對傳統生產法測量中人工誤差大、計算復雜、效率低等問題&#xff0c;結合誤差復映規律與剛度方程&#xff0c;通過高精度硬件與軟件協同&#xff0c;實現試件加工前后尺寸的在線采集、自動計算與報告生成&#xff0…