你從未見過的電腦
數一數你現在所在的房間裡有幾台電腦。多數人會說一台——筆電——卻漏掉了另外三十台。那台倒數到零的微波爐是電腦。牆上的溫控器、沙發上的遙控器、牙刷的充電座、口袋裡的車鑰匙也都是。它們沒有螢幕、沒有鍵盤、開機時也不會跳出視窗標誌。它們只是*做好自己那一件事*——加熱、調節、傳輸——從電源接通的那一刻起,一直做到報廢為止。這些就是嵌入式系統:埋藏在產品裡、專注於單一任務的電腦。
它與筆電的對比,正是整件事的關鍵。PC 是一台通用型機器:今天剪影片、明天打電動、下週跑試算表——你不斷載入新軟體。嵌入式系統恰恰相反。它的軟體在工廠就固定下來、幾乎永不更動;微波爐*永遠*學不會下西洋棋。這種專一不是缺陷,而是優點。正因為它只做一件事,所以能做得極小、極便宜、幾乎不耗電、瞬間開機,並且十年如一日地運轉,無人聞問。
微控制器:一整台電腦塞進一顆晶片
拆開一台桌上型 PC,你會看到一整座城市:這裡一顆處理器、那裡幾條記憶體、一顆獨立的硬碟、一張顯示卡,中間還纏著一團排線。典型嵌入式系統的大腦則樸素得多——它只是一顆指甲蓋大小、叫做微控制器(MCU)的晶片。MCU 的祕訣在於整合:它把處理器*和*記憶體*和*輸入/輸出電路統統塞進同一塊矽片,於是它本身就是一台幾乎不需要任何外援就能運轉的小電腦。
A PC (parts spread across a board) A MICROCONTROLLER (one chip)
┌──────────────────────────────────┐ ┌──────────────────────────────┐
│ CPU ──── RAM (DRAM sticks) │ │ CPU core │
│ │ ──── Disk (SSD, separate) │ │ Flash (program lives here) │
│ │ ──── GPU card │ │ RAM (scratch memory) │
│ │ ──── I/O chips on board │ │ Peripherals: GPIO, timers, │
│ many chips, big board, ~watts │ │ UART, I2C, SPI, ADC... │
└──────────────────────────────────┘ │ ~a few mW, ~$0.50–$5 │
└──────────────────────────────┘
General purpose, runs ANY software One job, runs ITS firmware三樣材料最關鍵。CPU 是真正執行指令的部分——取指、解碼、做算術——但在 MCU 裡它很樸實,常常只跑在幾百萬赫茲到兩三百兆赫,相較於筆電的數十億赫茲(GHz)。記憶體有兩種:一小塊用來打草稿、斷電就消失的 RAM,和一大塊永久存放程式的 flash(快閃記憶體)。最後是周邊(peripherals)——讓晶片得以觸碰外界的內建電路:可以開關的接腳、計時器,以及叫做 UART、I²C、SPI 的串列匯流排。正是這些周邊,把一台計算機變成了一台*控制器*。
韌體:燒進晶片裡的程式
在 PC 上,軟體存在硬碟裡,你想用時才啟動它。微控制器上沒有硬碟、也沒有「啟動」這回事——程式就住在晶片的 flash 記憶體裡,電源一接通便*立刻*開始執行。因為這種軟體緊貼著硬體、半硬半軟,我們稱它為韌體(firmware)。它是晶片這輩子唯一會跑的程式,而且就算把電池拔掉它也不會消失,因為 flash 是非揮發性的——它無需電力也能記住,就像寫下的字條能撐過停電,腦中的念頭卻不能。
你在筆電上用 C 寫的程式碼,是怎麼凍結進一顆晶片裡的?靠的是一段每個嵌入式工程師一天要重複上百次、固定不變的儀式——編譯、燒錄、執行(build, flash, run)。你寫下原始碼,一個叫*編譯器*的工具把它翻譯成 CPU 看得懂的原始機器指令,你透過一條纜線把那些指令拷進晶片的 flash,接著晶片重置並開始執行它們。改動一行,你就再繞這個迴圈一次。
- 撰寫——用 C 之類的語言寫下你的韌體,精確描述每一支接腳與周邊該做什麼。
- 編譯(build)——編譯器把你人類可讀的程式碼變成一個二進位的機器指令檔,大小要塞得進 flash。
- 燒錄(flash)——燒錄工具透過 USB 或除錯纜線,把那個二進位檔拷進晶片的 flash 記憶體。
- 執行(run)——晶片重置;上電時它跳到你程式的起點並永遠執行下去,完全不需要作業系統。
Hello, world:閃爍一顆 LED
每一門領域都有它的第一道儀式。對網頁工程師而言是印出「hello, world」;對嵌入式工程師而言則是閃爍一顆 LED。沒有螢幕可以印字,所以晶片對世界說的第一句話,就是一盞閃動的燈。要讓它閃,MCU 會用上它的一支通用接腳——GPIO,也就是「通用輸入/輸出」。設定成輸出時,一支 GPIO 接腳就是一個韌體能撥動的開關:把它驅動到 HIGH,接腳就送出晶片的供應電壓(比如 3.3 V);驅動到 LOW,接腳就停在 0 V。一開一關地切換,接上去的 LED 就會眨眼。
MCU 3.3 V ┌──────────┐ │ │ │ R = 100 Ω ──┴── battery / supply │ GPIO ──┼───[ ▭▭▭ ]───►|───┐ ───── │ (pin) │ resistor LED │ │ │ │ (~2V) │ │ │ GND ───┼────────────────────┴─────────┘ └──────────┘ Pin HIGH (3.3 V) → current flows → LED ON Pin LOW (0 V) → no current → LED OFF The series resistor is NOT optional — it limits the current so the LED (and the pin) don't burn out.
美妙之處在於:點亮那顆 LED,正是電路課程裡那套電壓與電流的故事,只是現在由軟體來驅動。接腳供給 3.3 V。LED 一旦點亮,本身會壓掉約 2 V,於是電阻分到剩下的 3.3 − 2 = 1.3 V。套用歐姆定律,電阻就決定了流過整條支路的電流:
Pin drives HIGH = 3.3 V LED forward drop ≈ 2.0 V (typical red LED) Voltage left for the resistor: V_R = 3.3 V − 2.0 V = 1.3 V Choose R = 100 Ω. Current through the LED: I = V_R / R = 1.3 V / 100 Ω = 0.013 A = 13 mA 13 mA is a healthy, bright, SAFE LED current. (A GPIO pin can usually source up to ~20 mA — stay under it.) Leave out the resistor (R ≈ 0) and I shoots toward hundreds of mA — the LED and the pin cook. The resistor is what keeps everything civilised.
仔細看 LED 的符號——那個帶一橫槓的小三角形。那枝箭頭意味著電流只准單向通過;LED 是一種電流的單向閥門,和電晶體、二極體一樣,都源自同一套半導體魔法,是表親關係。韌體完全不在乎這些。它只是往接腳寫個 1 或 0,剩下的交給物理。這道交棒——一行軟體指揮一股電子流過一個真實元件——正是嵌入式系統的全部精髓,全濃縮在一盞閃爍的燈裡。
把它串起來:永不止息的迴圈
那麼真正的韌體長什麼樣子?幾乎每支嵌入式程式都共享同一個骨架:一小段在上電時只跑一次的初始化(setup),後面接著一個跑到斷電為止的無窮迴圈。微波爐的迴圈檢查按鍵、更新時鐘;LED 的迴圈則只是把接腳打開、等待、關掉、等待,如此反覆。沒有「結束」、沒有「離開」——一支嵌入式程式生來就是要*永遠*跑下去的。
// Blink an LED on a GPIO pin — the embedded 'hello, world'
int main(void) {
gpio_set_output(PIN13); // SETUP: runs once at power-up
while (1) { // LOOP: runs forever
gpio_write(PIN13, HIGH); // pin = 3.3 V → LED on
delay_ms(500); // wait half a second
gpio_write(PIN13, LOW); // pin = 0 V → LED off
delay_ms(500); // wait half a second
} // ...and back to the top, forever
}這條學習路徑將通往何方
你現在握有這條路徑後續所有內容賴以建立的四個概念:嵌入式系統是埋在產品裡、用途固定的電腦;微控制器是把那台電腦熔進單一晶片——CPU、記憶體與周邊合而為一;韌體是永久住在它 flash 裡的那支唯一程式;而 GPIO 接腳則是這支韌體伸手撥動真實電流、與外界互動的最簡單方式,受你早已熟悉的同一條歐姆定律支配。
從這裡開始,這條路徑會一次加進一個周邊。你會學到如何讓那顆 LED 平順地調光,而不只是開或關(脈寬調變);如何在按鈕被按下的瞬間做出反應、又不浪費電力去不停輪詢(中斷);如何精準計時(計時器);以及如何讓你的晶片*開口說話*——透過串列匯流排把資料送給感測器和其他晶片。每個新周邊都是韌體觸碰物理世界的又一種方式。但這一切,都立基於這第一級台階:一支程式、一支接腳,和一股你能預測的電流。