關閉

第13章 Arduino SPI 教學:MOSI、MISO、SCK、SS 與 Uno 接線

本章完整介紹 SPI(Serial Peripheral Interface)高速序列通訊原理,說明 MOSI、MISO、SCK、SS/CS 四條訊號線的功能,以及 Arduino Uno R3 的 SPI 腳位配置。內容包含多個 SPI 裝置的連接方式、SPI.h 與 SPI.begin() 基礎程式、SD Card、TFT LCD、Ethernet Shield 等常見應用,並比較 SPI、I²C 與 UART 的差異,同時整理電壓相容、共地、CS 衝突及常見接線錯誤。

SPI(Serial Peripheral Interface)是一種常見的同步序列通訊協定,特色是傳輸速度快、架構直接,適合 Arduino 與 SD Card、TFT LCD、Ethernet Shield、Flash Memory 等需要較高資料傳輸量的模組。

本章將從 SPI 的工作原理開始,說明 MOSI、MISO、SCK、SS(CS)四條訊號線、Arduino Uno R3 的硬體 SPI 腳位、多裝置接線方式,以及 SPI、I²C、UART 三種通訊介面的差異。

實作時除了正確接線,也必須確認所有裝置共地、SS 腳位控制方式與邏輯電壓是否相容。Arduino Uno 使用 5V 邏輯,而部分 SPI 模組只接受 3.3V 訊號,必要時應使用電平轉換器。

本章學習目標

什麼是 SPI?

SPI 是 Serial Peripheral Interface 的縮寫,中文通常稱為「序列周邊介面」。它最初由 Motorola 提出,是一種由時脈訊號同步資料傳輸的序列通訊協定。

SPI 最大的優點是速度快、控制方式簡單,而且可同時傳送與接收資料,因此常用於大量或高速資料交換的周邊裝置。

常見的 SPI 裝置包括 SD Card、TFT LCD、Ethernet Shield、Flash Memory 與部分 RFID 讀卡模組。

SPI 為什麼通常比 I²C 快?

I²C 主要使用 SDA 與 SCL 兩條線,其中 SDA 是共用資料線,裝置必須在同一條資料線上輪流傳送與接收資料。

SPI 則使用 MOSI 與 MISO 兩條獨立資料線。MOSI 負責由 Master 傳送至 Slave,MISO 負責由 Slave 傳回 Master,因此可以同時送出與接收資料。

除了全雙工架構之外,SPI 通常沒有 I²C 位址傳輸與確認機制所造成的額外負擔,因此在硬體與裝置條件允許時,通常能提供較高的傳輸速度。

SPI 的四條訊號線

MOSI:Master 傳送資料給 Slave

MOSI 是 Master Out Slave In 的縮寫。當 Arduino 擔任 Master 時,MOSI 用來將資料從 Arduino 傳送到周邊裝置。

MISO:Slave 傳回資料給 Master

MISO 是 Master In Slave Out 的縮寫。當 Arduino 擔任 Master 時,MISO 用來接收由周邊裝置傳回的資料。

SCK:同步資料傳輸的時脈

SCK 是 Serial Clock 的縮寫,由 Master 產生同步時脈。MOSI 與 MISO 上的資料會依照 SCK 的節奏逐位移動與取樣。

SS(CS):選擇目前要通訊的裝置

SS 是 Slave Select 的縮寫,也常稱為 CS(Chip Select)。Master 透過 SS 告訴特定 Slave 何時開始或停止通訊。

多數 SPI 裝置的 SS 為低電位有效。開始通訊前將對應的 SS 拉低,完成後再拉高。實際有效電位仍應以模組或晶片資料表為準。

Arduino Uno R3 的 SPI 腳位

Arduino Uno R3 使用 ATmega328P 的硬體 SPI 控制器。標準數位腳位配置如下。

SPI 訊號也會出現在 Uno R3 的 ICSP 接頭,因此部分 Shield 會直接透過 ICSP 接頭取得 MOSI、MISO 與 SCK。

D10 是 Uno R3 預設的 SS 腳位,但專案中的周邊裝置可以使用其他數位腳位作為各自的 CS。當 Uno 擔任 SPI Master 時,仍應將硬體 SS 腳位設定為輸出,以避免控制器意外切換為 Slave 模式。

SPI 的基本通訊流程

假設 Arduino 要與 SD Card 通訊,Arduino 會透過 MOSI 將命令或資料送到 SD Card,透過 MISO 接收回傳資料,並以 SCK 提供同步時脈。

開始傳輸前,Arduino 將 SD Card 對應的 SS 拉低;傳輸完成後,再將 SS 拉高,使裝置離開目前的通訊狀態。

Arduino(Master)
│
├── MOSI ─────► SD Card
├── MISO ◄───── SD Card
├── SCK  ─────► SD Card
└── SS   ─────► SD Card

如何連接多個 SPI 裝置

SPI 可以連接多個 Slave。MOSI、MISO 與 SCK 通常由所有裝置共用,但每個裝置必須有自己的 SS(CS)腳位。

例如 SD Card 使用 D4、TFT LCD 使用 D7、Ethernet 控制器使用 D10 作為各自的 CS。Arduino 只將目前要通訊的裝置 CS 拉低,其餘裝置保持高電位。

若多個裝置的 CS 同時為 LOW,可能有多個 Slave 同時驅動 MISO,造成匯流排衝突、資料錯誤,甚至增加硬體風險。

Arduino(Master)
│
├── MOSI ─────┬──► SD Card
│             ├──► TFT LCD
│             └──► Ethernet
├── MISO ◄────┬──── SD Card
│             ├──── TFT LCD
│             └──── Ethernet
├── SCK  ─────┬──► 所有裝置
├── D4   ─────────► SD Card CS
├── D7   ─────────► TFT LCD CS
└── D10  ─────────► Ethernet CS

使用 Arduino SPI.h 函式庫

Arduino 的硬體 SPI 功能由 SPI.h 函式庫提供。程式開頭先引入 SPI.h,再於 setup() 中呼叫 SPI.begin() 初始化 SPI 控制器。

初始化完成後,即可搭配 SD、Ethernet、TFT 或其他裝置專用函式庫使用。實際裝置通常還需要設定 CS 腳位與裝置本身的初始化參數。

#include <SPI.h>

void setup()
{
  SPI.begin();
  Serial.begin(9600);
  Serial.println("SPI Ready");
}

void loop()
{
}

上傳程式後,可開啟 Serial Monitor 並將鮑率設定為 9600。預期會看到 SPI Ready,代表程式已執行 SPI.begin()。這只能確認初始化程式已執行,不代表外部 SPI 模組已完成連線或通訊。

SPI 常見應用模組

並非所有同類型模組都固定使用 SPI。例如 RC522 常使用 SPI,而 PN532 依模組設計與跳線設定,可能支援 I²C、SPI 或 UART。接線前應確認模組版本、介面模式與資料表。

SPI 與 I²C 的差異

UART、I²C 與 SPI 完整比較

電壓相容與接線安全

Arduino Uno R3 的數位邏輯通常為 5V,但許多現代 SPI 晶片與模組使用 3.3V 邏輯。不能只因模組板上有 5V 電源腳位,就假設所有訊號腳都可直接承受 5V。

部分 SD Card 或 TFT 模組已內建穩壓器與電平轉換,但也有模組只提供穩壓而未完整轉換 MOSI、SCK、CS 等訊號。接線前應查看模組規格或電路圖。

若裝置的輸入腳不耐 5V,應使用適合 SPI 時脈速度的雙向或單向電平轉換電路。所有裝置的 GND 必須相連,否則訊號缺少共同參考電位,通訊可能不穩定或完全失敗。

初學者常見錯誤與故障排除

MOSI 與 MISO 接反

先以 Arduino 為 Master 判斷方向:MOSI 是 Arduino 輸出到模組,MISO 是模組輸出到 Arduino。若兩者接反,通常無法正確讀寫資料。

SS 或 CS 腳位未接或設定錯誤

確認程式設定的 CS 腳位與實際接線相同。多數模組在 CS 為 LOW 時啟用,但仍應以模組資料表與函式庫文件為準。

多個裝置同時被選取

初始化時先將所有 CS 腳位設為 OUTPUT 並拉高。一次只將目標裝置的 CS 拉低,完成傳輸後立即拉高,避免多個 Slave 同時驅動 MISO。

忘記呼叫 SPI.begin()

若直接操作 SPI 或裝置函式庫沒有代為初始化,必須在 setup() 中呼叫 SPI.begin()。同時確認相關函式庫是否要求先初始化 SPI,再初始化模組。

沒有共地

Arduino、SPI 模組與外部電源必須共用 GND。沒有共同接地時,即使 MOSI、MISO、SCK 與 CS 都接對,也可能出現無回應、資料錯亂或偶發失敗。

時脈模式或速度不相容

不同 SPI 裝置可能要求不同的 Clock Polarity、Clock Phase 與最高時脈。使用裝置專用函式庫時通常會處理這些設定;若自行使用 SPI.transfer(),應依資料表設定 SPI Mode、資料順序與時脈。

多個裝置共用 SPI 匯流排時,不應假設所有裝置都使用相同設定。較完整的程式會在每次通訊前使用對應的 SPISettings。

模組可供電但無法通訊

模組上的電源指示燈亮起,只能代表已供電,不代表邏輯電壓、介面模式、腳位或初始化參數正確。應逐項確認 VCC、GND、MOSI、MISO、SCK、CS,以及模組是否被設定為 SPI 模式。

本章實作練習

練習一:完成 SPI 初始化

建立一個 Arduino 程式,引入 SPI.h,並在 setup() 中執行 SPI.begin()。透過 Serial Monitor 顯示初始化訊息,確認程式流程已執行。

練習二:確認 Arduino Uno SPI 腳位

在 Arduino Uno R3 板上找出 D11、D12、D13、D10 與 ICSP 接頭,分別標記 MOSI、MISO、SCK 與 SS。

練習三:準備 SD Library

確認 Arduino IDE 中可使用 SD Library,並先閱讀範例程式使用的 CS 腳位。完整的 SD Card 讀寫、格式與檔案操作可在後續專章實作。

Challenge:選擇正確的通訊介面

常見問題 Q&A

SPI 一定需要四條線嗎?

標準全雙工 SPI 通常使用 MOSI、MISO、SCK 與 SS。某些只寫入的顯示器可能不使用 MISO,部分裝置也可能採用三線式或其他變形介面,因此仍應以裝置資料表為準。

多個 SPI 裝置可以共用同一組腳位嗎?

可以。MOSI、MISO 與 SCK 通常可以共用,但每個裝置需要獨立的 CS。還要確認不同裝置的 SPI Mode、時脈上限、電壓與函式庫是否能在同一條匯流排上正確切換。

SPI 裝置需要位址嗎?

一般不需要像 I²C 一樣設定裝置位址。Arduino 透過各裝置獨立的 CS 腳位選擇通訊對象。

可以把任意數位腳位當成 CS 嗎?

多數情況可以使用一般數位輸出腳位作為周邊裝置的 CS,但必須與程式設定一致。Arduino Uno 擔任 Master 時,硬體 SS 腳位 D10 仍建議設定為輸出。

為什麼同一個模組在不同程式中速度不同?

實際速度會受到 Arduino 時脈、SPI Clock 設定、模組上限、接線品質、線長、電平轉換器與函式庫實作影響。高速傳輸時,過長杜邦線與品質不佳的接點更容易造成錯誤。

本章重點整理

下一章預告

下一章將介紹 Arduino 常用函式與程式設計技巧,包括 pinMode()、digitalWrite()、digitalRead()、analogRead()、analogWrite()、delay()、millis()、map()、constrain() 與 random(),並透過實際範例說明如何寫出更容易維護的 Arduino 程式。