常見介面 I2C, SPI, UART 教材
本頁整理嵌入式系統與 IoT 裝置最常見的三種通訊介面:I2C、SPI、UART。內容包含基本原理、接線方式、時序觀念、常見除錯方法,以及 Python / MicroPython 範例與常用模組。
I2C
SPI
UART
Raspberry Pi
Pico W
ESP32
一、為什麼要學通訊介面
- 感測器、螢幕、記憶體、GPS、藍牙模組都需要與主控板交換資料。
- 不同模組不一定使用同一種通訊方式。
- 選對介面可以降低接線難度、提升速度,並減少除錯時間。
- 理解介面後,便能從 datasheet、接線圖與時序圖判斷模組的通訊需求。
二、先記住的總結
- I2C:兩條線、可掛多裝置,常用於多感測器與低速周邊。
- SPI:速度快、全雙工、常用於顯示器與高速周邊。
- UART:最直觀、最像序列埠,常用於除錯、GNSS、藍牙與數據機模組連接。
建議的學習順序可先從 UART 開始,再進入 I2C,最後學習 SPI,以便循序掌握序列通訊、位址機制與時序控制。
三、三種介面的整體比較
| 項目 |
I2C |
SPI |
UART |
| 線數 | 2 條主線(SDA, SCL) | 至少 4 條(MOSI, MISO, SCLK, CS) | 2 條主線(TX, RX) |
| 拓樸 | 多主/多從匯流排 | 單主多從較常見 | 點對點 |
| 位址機制 | 有裝置位址 | 通常靠 CS 選擇裝置 | 無位址概念 |
| 速度 | 低到中 | 高 | 中 |
| 全雙工 | 否 | 是 | 通常可雙向,但不如 SPI 典型 |
| 適合裝置 | 感測器、RTC、EEPROM | TFT、ADC、Flash、RF 模組 | GPS、藍牙、序列除錯 |
| 上手門檻 | 中 | 中偏高 | 低 |
四、I2C 介面
1. 基本觀念
SDA:資料線
SCL:時脈線
- 每個裝置都有位址,常見為 7-bit 位址。
- 多個裝置可以掛在同一組 SDA / SCL 上。
2. I2C 為什麼常用於感測器
- 接線少
- 可讓一台主控板同時連接多個環境感測器
- 許多常見模組都提供 I2C 介面與現成函式庫
3. 常見問題
- 忘了接上拉電阻(pull-up resistor)
- 位址衝突:兩個裝置位址相同
- 電壓不相容:3.3V 裝置與 5V 裝置直接混接
- 線太長、干擾太大導致通訊不穩
4. 重要術語
| 術語 | 說明 |
| Start Condition | 主機開始一筆 I2C 傳輸的訊號。 |
| Stop Condition | 主機結束一筆 I2C 傳輸的訊號。 |
| ACK / NACK | 接收端是否確認收到資料。 |
| 7-bit address | 最常見的裝置位址格式。 |
| Pull-up resistor | SDA、SCL 常需要上拉到高電位。 |
5. Raspberry Pi Python 範例概念
from smbus2 import SMBus
I2C_BUS = 1
DEVICE_ADDR = 0x48
REGISTER = 0x00
with SMBus(I2C_BUS) as bus:
data = bus.read_byte_data(DEVICE_ADDR, REGISTER)
print("read:", data)
6. Pico W MicroPython 掃描 I2C 位址
from machine import Pin, I2C
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)
print('devices:', [hex(x) for x in i2c.scan()])
實作時可先使用 i2c.scan() 確認匯流排上可偵測到的裝置位址,再進入寄存器讀寫。
五、SPI 介面
1. 基本觀念
MOSI:Master Out, Slave In
MISO:Master In, Slave Out
SCLK:時脈
CS / SS:晶片選擇
2. SPI 的特點
- 速度通常比 I2C 快
- 常見於顯示器、外部 Flash、高速 ADC
- 每個從屬裝置通常需要一條獨立的 CS 線
3. 為什麼 SPI 比較快
- 沒有 I2C 的位址仲裁與 ACK/NACK 流程負擔
- 可全雙工傳輸
- 時序結構相對直接
4. 實作時要特別注意
- SPI 沒有統一的「位址掃描」概念
- 不同裝置的
CPOL、CPHA 可能不同
- CS 拉低與拉高的時機很重要
5. SPI Mode 概念
| Mode | CPOL | CPHA | 說明 |
| Mode 0 | 0 | 0 | 最常見,時脈閒置低,前緣取樣 |
| Mode 1 | 0 | 1 | 時脈閒置低,後緣取樣 |
| Mode 2 | 1 | 0 | 時脈閒置高,前緣取樣 |
| Mode 3 | 1 | 1 | 時脈閒置高,後緣取樣 |
6. MicroPython 範例
from machine import Pin, SPI
spi = SPI(0, baudrate=1000000, polarity=0, phase=0,
sck=Pin(18), mosi=Pin(19), miso=Pin(16))
cs = Pin(17, Pin.OUT)
cs.value(0)
spi.write(b'\x9F')
chip_id = spi.read(3)
cs.value(1)
print(chip_id)
SPI 裝置最常見的錯誤不是「完全沒接好」,而是 mode 設錯、CS 切換時機不對、或 baudrate 太高。
六、UART 介面
1. 基本觀念
TX:傳送線
RX:接收線
- 接線規則通常是
TX → RX、RX → TX
- 雙方要設定相同 baud rate
2. UART 最常見的參數
| 參數 | 常見值 | 說明 |
| Baud rate | 9600, 115200 | 每秒傳輸符號速率 |
| Data bits | 8 | 資料位元數 |
| Parity | None / Even / Odd | 同位檢查 |
| Stop bits | 1 或 2 | 結束位元 |
3. UART 適合哪些場景
- 連接 GPS 模組
- 連接藍牙模組
- 序列除錯輸出
- 兩塊板子之間傳送簡單字串或封包
4. MicroPython 範例
from machine import UART, Pin
import time
uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
while True:
uart.write('hello from pico\n')
if uart.any():
msg = uart.read()
print(msg)
time.sleep(1)
5. Raspberry Pi Python 範例
import serial
ser = serial.Serial('/dev/serial0', 115200, timeout=1)
ser.write(b'hello from pi\n')
print(ser.readline().decode(errors='ignore'))
UART 很適合用於「Pico W 傳資料給 Raspberry Pi」這類情境,因為資料內容可直接以字串形式觀察與除錯。
七、常用元件與模組範例
下面整理一些常見且容易取得的模組。這些連結可作為查閱 datasheet、接線圖與函式庫範例的起點。
1. I2C 常用元件
2. SPI 常用元件
3. UART 常用元件
若要建立基礎模組組合,可從 I2C 的 BME280 與 OLED、SPI 的 MicroSD 或 TFT、UART 的 GPS 與藍牙模組開始。
八、接線觀念與電壓注意事項
- 先確認裝置工作電壓:3.3V 或 5V。
- Raspberry Pi 與 Pico W 大多是 3.3V 邏輯,不可直接承受 5V GPIO。
- 共地(GND)通常是通訊成功的前提。
- UART 錯接最常見是 TX/RX 沒交叉;I2C 錯接最常見是 SDA/SCL 對調;SPI 錯接最常見是 CS 沒接或接錯。
裝置成功供電不代表通訊一定成功;電壓、共地、腳位與協定參數都必須同時正確。
九、如何選擇 I2C、SPI、UART
| 情境 | 建議介面 | 原因 |
| 多個低速感測器 | I2C | 接線省、可共用匯流排 |
| 高速顯示器或外部記憶體 | SPI | 速度高、時序直接 |
| 模組除錯與字串傳輸 | UART | 容易理解、終端機可直接觀察 |
| 兩塊板子先做簡單通訊實驗 | UART | 最容易做出第一個成功結果 |
十、常見除錯方法
1. I2C 除錯
- 先掃描位址,看裝置有沒有被偵測到
- 檢查 pull-up 電阻是否存在
- 降低頻率,例如從 400kHz 改成 100kHz
2. SPI 除錯
- 確認 datasheet 的 SPI mode
- 先把 baudrate 降低
- 檢查 CS 的拉低/拉高時序
3. UART 除錯
- 確認 baud rate 一致
- 確認 TX/RX 有交叉接
- 確認雙方都共地
4. 進階工具
- 邏輯分析儀(logic analyzer)
- 示波器
- 序列埠監看工具
加入 logic analyzer 觀察時序波形,有助於對照程式碼、腳位訊號與協定行為。