首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

嵌入式系統軟體架構設計精要:模組劃分、任務模型與驅動開發

     編輯:關於C語言

前言:軟體架構是系統的靈魂

結構混亂的程式碼不僅難讀,更導致除錯、測試、維護、升級成本指數級上升。本文從嵌入式系統實戰角度,系統闡述軟體架構設計的核心原則與落地技巧。

一、模組劃分:高內聚、低耦合的 C 語言實踐

C 語言屬結構化程式設計,模組劃分以「功能」為主軸(註:面向物件中以資料為主軸)。

模組實體定義

  • 一個 .c 檔 + 一個 .h 檔
  • .h 僅含介面宣告(extern 函數/變數)
  • .c 內部函數與全域變數加 static 隱藏

鐵律:.h 檔絕不定義變數

錯誤範例:

/* module1.h */ int a = 5;  // 定義,會配置記憶體
/* module1.c */ #include "module1.h"
/* module2.c */ #include "module1.h"  // 每個 .c 都產生一份 a!

正確做法:

/* module1.h */ extern int a;  // 僅宣告
/* module1.c */ #include "module1.h"; int a = 5; // 定義在 .c
/* module2.c */ #include "module1.h"  // 共用同一個 a

嵌入式系統兩大模組類別

  1. 硬體驅動模組:一顆晶片對應一個模組
  2. 軟體功能模組:業務邏輯封裝,滿足高內聚、低耦合

二、多任務 vs. 單任務:架構選型決策

核心差異

決策指南

  • 手機協定棧:多任務
  • 小靈通協定棧:單任務(主迴圈輪詢模擬並發)
  • 原則:軟體規模、即時性、硬體資源三者權衡

三、單任務系統典型架構


// 啟動流程
_reset -> startup.asm -> main()

int main() {
    // 1. 硬體初始化
    hw_init_all();

    // 2. 軟體模組初始化
    sw_module_init_all();

    // 3. 進入死迴圈(超級迴圈)
    while (1) {  // 推薦 while(1),語意明確
        module1_process();
        module2_process();
        // ...
    }
}

死迴圈的哲學

  • 作業系統是死迴圈
  • Win32 訊息迴圈是死迴圈
  • 嵌入式主程式是死迴圈
  • 執行緒處理函數是死迴圈

系統需運行到世界末日,除非看門狗重啟。過度追求「優雅退出」反而增加複雜度。

常見反模式

for (;;) { }  // 語意不明確,需知 C 語言規則才懂是無限迴圈

四、中斷服務程式 (ISR) 設計鐵律

標準 C 不支援中斷,編譯器擴充關鍵字(如 __interrupt、#pragma interrupt)。

ISR 四大原則

  1. 無回傳值
  2. 無參數傳遞
  3. 極短極快:只做必要硬體操作與資料緩衝
  4. 嚴禁呼叫 printf 等非重入/耗時函數

最佳實踐:中斷佇列 + 主迴圈分發


typedef struct IntQueue {
    int intType;
    struct IntQueue *next;
} IntQueue;

IntQueue *gpIntQueueHead = NULL;

__interrupt void UART_Isr() {
    int type = GetInterruptType();
    QueueAddTail(&gpIntQueueHead, type);  // 僅入佇列
}

// 主迴圈
while (1) {
    if (!IsIntQueueEmpty()) {
        int type = GetFirstInt();
        switch (type) {  // 類訊息驅動機制
            case INT_UART_RX: handle_uart_rx(); break;
            case INT_TIMER:   handle_timer(); break;
            // ...
        }
    }
    // 其他模組輪詢...
}

ISR 極精簡,實際處理移至主迴圈,避免中斷巢狀與阻塞問題。

五、硬體驅動模組標準化介面

每個驅動模組應包含:

  1. ISR
  2. 硬體初始化
    • 設定暫存器參數(鮑率、採樣率...)
    • 登記中斷向量表
  3. 設定 CPU 控制線(PIO/中斷觸發模式/屏蔽位)
  4. 操作介面函數群(如 LCD:畫點、畫線、顯示字元;RTC:讀/寫時間)

中斷向量表登記範例 (80186)


void far *m_myPtr = make_far_pointer(0L);  // 0x0000:0x0000
m_myPtr += ITYPE_UART;                     // 偏移至 UART 向量
*m_myPtr = &UART_Isr;                      // 填入 ISR 位址

六、C 語言模擬物件導向:封裝資料與行為

利用結構體 + 函數指標模擬「類別」:


#define C_Class struct

C_Class A {
    C_Class A *A_this;              // this 指標
    void (*Foo)(C_Class A *A_this); // 方法:函數指標
    int a;                          // 資料成員
    int b;
};

可進一步實現封裝、繼承、多型,但嵌入式開發中,核心價值在於解決資料與函數脫節、架構分散的問題,而非追求純粹的 OO 模擬。

總結

軟體架構決定系統成敗。模組劃分遵循高內聚低耦合,任務模型依複雜度選型,單任務採超級迴圈,中斷採佇列分離,驅動模組標準化介面,必要時以 C 模擬 OO 封裝。記住:結構清晰的程式碼,是對未來維護者最大的善意。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性單任務系統多任務系統
執行模式巨觀串列巨觀並行(微觀可能串列)
核心依賴無 OS 或簡易調度器多任務 OS (VxWorks, μC/OS, Linux...)
任務管理主迴圈輪詢TCB + 排程器 + 上下文切換
適用場景簡單控制、資源極受限複雜系統、即時性要求高