在單片機上實現“多線程”的方法有幾種,下面按照從簡單到復雜、從輕量到系統性來列出常見的方案:
🧵 一、偽多線程(最輕量)
方法:主循環 + 狀態機 / 定時器輪詢
-
主循環中輪流調用各個任務的處理函數,每個任務保存自己的狀態。
-
沒有真正的上下文切換,適合資源極少的 8/16 位 MCU。
-
每個任務必須是“非阻塞”的,不能使用
delay
。
while (1) {task1();task2();task3();
}
優點:
-
簡單、高效、占用資源極少。
-
不需要堆棧切換,不需要操作系統。
缺點:
-
不是真正的多線程,不能處理阻塞任務。
🕒 二、基于中斷的任務分發
方法:中斷觸發事件 + 主循環消費
-
中斷中設置標志或將事件放入隊列;
-
主循環中根據事件執行任務處理。
volatile int flag = 0;void USART_IRQHandler() {flag = 1;
}int main() {while (1) {if (flag) {handle_uart();flag = 0;}}
}
優點:
-
響應快,適合 IO 驅動型任務。
-
不涉及線程切換和堆棧管理。
缺點:
-
中斷中不能做太多事,邏輯要分拆。
🧠 三、協程(Coroutine)
方法:使用 switch
或 Duff's device
實現偽線程
-
基于狀態保存和跳轉的方式,實現類似線程掛起和恢復的機制。
-
只使用一個棧,代碼結構像線程。
#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(x) do { state=__LINE__; return x; case __LINE__:; } while (0)
#define crEnd }int task() {crBegin;crReturn(1);crReturn(2);crEnd;
}
優點:
-
沒有線程上下文切換。
-
寫法更接近同步邏輯。
缺點:
-
不是真正的線程,不支持阻塞等待。
🧵 四、基于 RTOS(真正多線程)
方法:使用輕量級操作系統(如 FreeRTOS、RT-Thread)
-
每個線程有獨立棧空間;
-
內核實現任務調度、搶占式多任務;
-
支持優先級、信號量、消息隊列、互斥鎖等。
void task1(void *arg) {while (1) {do_something();vTaskDelay(1000);}
}
xTaskCreate(task1, "T1", 128, NULL, 1, NULL);
優點:
-
真正多線程,支持阻塞、同步。
-
易于模塊化和擴展。
缺點:
-
占用資源高(Flash/RAM)、上手略有門檻。
-
對調度和資源管理有更高要求。
🛠 五、軟調度器(TinyOS、protothread等)
方法:輕量調度框架(介于 FSM 和 RTOS 之間)
-
有些庫如
protothread
,用極少資源實現多任務編排; -
適合資源受限又希望更接近線程體驗的項目。
總結表格:
方法 | 是否真多線程 | RAM占用 | 復雜度 | 是否阻塞 | 推薦場景 |
---|---|---|---|---|---|
主循環 + FSM | 否 | 低 | 低 | 否 | 資源極少,超低功耗 |
中斷觸發 | 否 | 低 | 中 | 否 | IO驅動系統 |
協程 | 否 | 低 | 中 | 否 | 寫法優雅但簡單任務 |
RTOS | 是 | 中~高 | 高 | 是 | 任務多、同步復雜 |
輕量調度器 | 否 | 低 | 中 | 部分支持 | 資源受限但邏輯復雜 |
評論中告訴我你用的是哪種 MCU,我們可以一起探討一個適合你的“多線程”實現方式。