隨著科技的演進, 在單晶片微控制器及 SoC 的領域中, SPI 及 I2C 這二種串列 (序列) 介面變得十分常見. 這二者與主機間通訊用的非同步串列通訊埠 RS-232 (UART) 非常不一樣

  • 二個都是同步傳輸介面, 主要是用於 CPU 和週邊晶片之間.
  • SPI 及 I2C 二者設計的主要目的在於減少 CPU 和週邊晶片之間的接腳數.
  • SPI 一般需要 4 條接線 (至少三條), 而 I2C 則只要二條線, 這和早期常用的並列匯流排動輒十數條接線有著明顯的差異.
  • SPI 的硬體結構簡單而且傳輸速度快, 一般是 5M/10M/20Mbps 或是更快 (可以到 200Mbps), I2C 的傳輸速度則只有 100Kbps/400Kbps/1Mbps(/3.4Mbps/單向5Mbps).
  • SPI 是全雙工, I2C 則是半雙工.
  • SPI 使用硬體線路來指定 slave 晶片, I2C 則在傳送的第一個位元組上指定 (7bit位址).
  • SPI 不提供交握機制, 無法確認 slave 晶片是否有跟上. I2C 則有雙向的確認機制.

本篇介紹的是 SPI 介面



SPI 簡介


SPI 是 Serial Peripheral Interface 的縮寫, 中文意思是串列週邊介面, 該介面是由 Motorola 公司設計發展的高速同步串列介面, 原先是應用在其 68xx 系列的 8 位元處理器上 (1985 年首次出現在 M68HC11 處理器上, 並提供了完整之說明文件), 用以連接 ADC, DAC, EEPROM, 通訊傳輸 IC...等週邊晶片. 由於具備有低接腳數, 結構單純, 傳輸速度快, 簡單易用...等特性, 目前已經成為業界慣用標準: 不只是單晶片微控制器上有, 許多新的 SoC 晶片直接就支援多組 SPI 介面, 甚至普及到連模組化的產品 (如: 手機用的 LCD 模組 (SDI 介面), 相機模組) 及 3C 產品 (如: 數位相機用的記憶卡) 也都是使用 SPI 介面.

備註: 早期數位相機用的 MMC (Multi Media Card) 記憶卡是直接使用 SPI 相容的介面, 新式的 SD 卡為了加快傳輸速度雖然擴充了接腳定義, 但也還保留了舊式 SPI 介面相容的模式. 參看 How to Use MMC/SDC

SPI 架構及介面接腳


SPI 為一主從式架構, 通常有一個 Master (主設備) 和一個 (或多個) Slave (從設備). 介接方法及內部硬體結構很簡單, 如下面的示意圖:

SPI HW Structure

SPI 結構示意圖 (傳輸部份)

介面上總共有 4 支接腳:

SPI 接腳名稱及意義
接腳名稱 中文 說明
MOSI 主出從入 master 數據輸出, slave 數據輸入
MISO 主入從出 master 數據輸入, slave 數據輸出
SCLK 時脈訊號 時脈信號, 由 master 產生並控制
/SS 晶片致能 slave 選擇信號, 由 master 控制. slave 只有在 /SS 信號為低電位時, 才會對 master 的操作指令有反應.

介接時只要相同名稱接腳接在一起即可

SPI 的接腳有另一套常用的名稱:

  • SDO: Serial Data Out, 資料輸出 (不分主從)
  • SDI: Serial Data In, 資料輸入 (不分主從)
  • SCK: 對應 SCLK
  • /CS: 對應 /SS

由於這種標示方法不分主從, 資料輸出都是 SDO, 資料輸入都是 SDI, 所以介接時必需把二個設備的 SDOSDI 接腳對接: master 的 SDO 接到 slave 的 SDI, master 的 SDI 接到 slave 的 SDO.

在實際應用上, 如果不需要由 slave 讀回資料時 (如: Output Port Expander, 或者 DAC 晶片), 則 MISO 接腳可以省略. 有看到一部份資料說: 只有一主一從時, /SS 訊號可以省略, 只要將 slave 的 /SS 直接接地即可. 對某些 slave 晶片來說這是不對的, 因為有些 slave 晶片會拿 /SS 訊號的下降緣來識別 master 送來的第一個 bit. 這是非常重要的錯誤回復機制, 遇到這類 slave 晶片只把 /SS 接腳直接接地是不會動作的. 另外後述的 Daisy-Chain 接法也需要這個 /SS 訊號的上昇緣才能運作. Daisy-Chain 模式用它 (/SS 訊號的上昇緣) 來栓鎖指令, 如此多個 slave 晶片才能同時載入不同的指令.

由上面的結構示意圖, 我們很清楚的看出它其實是利用二組頭尾相連的位移暫存器 (Shift Rigister) 來完成 master 和 slave 之間的資料交換, 而且是接收與發送同時進行 (全雙工). 而 SCLK 就是用來控制二者同步位移的時脈信號, 它是由 master 產生送出給雙方的位移暫存器. 這樣子的結構允許資料一位元一位元的傳送, 可快可慢, 甚至允許暫停 (可以暫停在任意點上, 完全沒有限制), 因為 SCLK 沒有變動時, 雙方的 shift register 是不會有動作的. 所以如果你的微控制器沒有硬體式的 SPI 可以用, 直接用軟體加一般的 GPIO 接腳, 就可以模擬 SPI master. (用軟體模擬 SPI slave 則不建議, 因為如果我們不知道對方會送多快的 SCLK).

在介接方面, 除了簡單的一主一從架構之外, SPI 也可以一個 master 連接多個 slave. 接法上有二種, 一種是利用多條獨立的 /SS 訊號, 另一種則利用 Daisy-Chain 的方式.

SPI Multi-Slave

SPI Master 介接多個 Slave 的二種接法

使用 Daisy-Chain 的方法, 不需要額外的硬體接腳來擴充 /SS 訊號, 但是傳送及接收程式需要大改, 非常的麻煩. 另外還有一個障礙是, slave 晶片必需在同一個模式下工作, 還有也不能有接腳缺省的情形 (有許多 DAC 晶片沒有 MISO 接腳), 也因此常見的應用 Daisy-Chain 的例子都是用來串連多個同一型號的晶片, 例如: 需要多組 DAC 或者是 ADC 一起工作的情況. 另外要注意的是: 並非每一顆 SPI 晶片都可以支援 Daisy-Chain 的接法, 必需詳細檢視晶片的使用手冊是否有支援 Daisy-Chain 介接方法, 或者是檢視讀取的指令格式是否符合 Daisy-Chain 的需求. 否則到時候硬體接線接好了, Master 卻怎樣也無法命令 slave 晶片正常的工作.

Daisy-Chain 的運作方法是以倍數擴充每次傳輸的指令/資料長度 (有二個 slave 晶片串在一起, 傳輸長度就 x2; 三個 slave 晶片串在一起, 傳輸長度就 x3). 由於上一顆 slave 晶片的 MISO 是連接到下一顆 slave 晶片 MOSI, 所以多出來的傳輸訊號很自然把先前的訊號擠出來, 送到下一顆晶片. 等到所有訊號都送出去了, 再來就是利用 /SS 訊號的上昇緣來通知每一顆 slave 晶片: 要給你的指令/資料已經準備好了, 請把它栓鎖 (latch) 起來了. 同樣的讀回資料也會串在一起. 所以原本的驅動程式必需把要給各個 slave 晶片的指令暫存起來然後依 slave 晶片串連的次序將指令串起來再送出, 收回來的資料也必需先裁切好再依 slave 晶片串連的次序分配給對應的接收單元.

是故比較常用的是多條獨立的 /SS 訊號. 有的 master 晶片是直接提供額外的 /SS1, /SS2, /SS3...等接腳. 有的則需要利用原本的 /SS 再以一組 3to8 解碼器 (或者是 4to16 解碼器) 配合 3~4 條 GPIO 接腳來產生需要的多組 /SS. 更有的 SoC 乾脆提供多組 SPI 單元及多條獨立的 /SS 訊號 (當然的, 代價是 master 晶片的接腳數比較多, 單價拉高.).

SPI 工作模式及時序圖


使用 SPI, 最麻煩一件事是確認周邊晶片的工作模式. SPI 一共有 4 種工作模式, 但這 4 種模式的時序圖差異非常小, 常令初學者 '霧剎剎' 抓不到重點. 如下圖:

SPI Timming Chart

各種工作模式下的 SPI 時序圖

上圖的上半部是 SCLK 的時序, 有兩種選擇: CPOL=0 或者 CPOL=1. 中間及下半部是 MOSI MISO 的時序, 一樣是有兩種選擇: 中間是 MOSI MISO 是在 SCLK奇數次變化栓鎖資料, 下半部則是 MOSI MISO 是在 SCLK偶數次變化栓鎖資料.

解說:

  • SPI slave 晶片一般只支援一種工作模式, 所以通常 master 必需牽就 slave 把工作模式設成和 slave 一致, 才能正常運作. (因為二者內部均是位移暫存器, 所以 MOSIMISO 的時序需求是一樣)
  • 首先, 第一個不同是 SCLK 的極性 (polarity), 所謂極性其實是指 SPI 不工作時, SCLK 是停留在高電位還是低電位. CPOL=0 是 SCLK 在不工作時停留在低電位, CPOL=1 則是停留在高電位.
  • 再來要注意 slave 晶片是在 SCLK下降緣栓鎖資料, 還是在 SCLK 的上升緣. 要讓對方栓鎖資料, 我們就必需把資料 Hold 住, 保持穩定, 所以 Slave 晶片在 SCLK下降緣栓鎖資料, 相對的 master 就必需要在上升緣送出資料. 反之, slave 晶片在 SCLK 的上升緣栓鎖資料, 相對的 master 就必需要在下降緣送出資料.
  • 但是 CPHA 的定義並不是依上升緣/下降緣. CPHA 設定的是晶片栓鎖資料的時機是在 /SS 訊號下降之後, SCLK奇數次變化 (CPHA=0), 還是偶數次變化 (CPHA=1).
  • 所以 CPHA 配合 CPOL (SCLK 的極性) 設定, 組合起來一共有 4 種工作模式. 不過模式的命名順序出現了分歧沒有統一, 現有的晶片出現了二種順序 (參閱 Wiki 網站 Serial Peripheral Interface Bus). 所以撰寫程式時不要只是把 Mode 設成相同的數值, 小心 master 晶片和 slave 晶片二者的模式順序不同. 不過仔細對照一下, 差異只有 mode 的數值不同而已, CPOLCPHA 的定義並無不同.
    SPI Mode
    Mode # of
    Model A
    Mode # of
    Model B
    CPOL CPHA 資料栓鎖時機 MISO MOSI
    時序圖
    1 0 CPOL=0 CPHA=0 奇數 上升緣 上半組
    0 1 CPOL=0 CPHA=1 偶數次 下降緣 下半組
    3 2 CPOL=1 CPHA=0 奇數 下降緣 上半組
    2 3 CPOL=1 CPHA=1 偶數次 上升緣 下半組
    Model A: For ARM-based and Microchip PIC
    Model B: 其他
  • 一旦正確辨識出 slave 晶片的工作模式, 只要把 master 設定成一樣的工作模式即可正確的傳送指令及接收資料.

結語


總結一下辨識的技巧:

  • 先確認 slave 晶片需求的 SCLK 極性, 不工作時是在低電位還是高電位, 由此確認 CPOL 為 0 或 1.
  • 再由 slave 晶片 datasheet 中的時序圖確認 slave 晶片是在 SCLK下降緣栓鎖資料, 還是在 SCLK上升緣.
  • 直接比對上面的模式表, 確認出 CPHA 值為 0 或 1.
  • 確認傳輸時序圖是否正確 (是奇數組 SCLK 變化, 還是偶數組 SCLK 變化)

補充說明一點, 從 /SS下降緣到第一個 SCLK latch edge 有一小段時間的 delay, 這一小段 delay 必需滿足 slave device 的規格需求, 尤其是 SCLK 的頻率偏高的時候. 否取 slave device 會無法正常工作. 有些 MCU 的 SPI 硬體模組把這一段設成固定的 CLK 數; 有些 MCU 的 SPI 硬體模組則可以讓使用者自行調整. (2018/06/14)

還有一點在圖中有標示, 但上文沒有提到的是: SPI 的資料是 msb (Most Significant Bit)bit7 (MSB) 先傳 (傳輸的資料格式是 8 Bits 就 bit7 先傳, 是 16 Bits 就 bit15 先傳, 是 24 Bits 就 bit23 先傳), 如果你是用軟體來模擬 SPI master 需注意到這一點. 話雖如此, 有些許 MCU 的 SPI port 是允許你把它改為 lsb (Least Significant Bit) 先傳, 這是為了要能應付一些沒有依照標準設計的晶片, 並不是標準狀況, 也請小心.

另外 SPI 只是硬體的傳輸協定, 完全沒有提及定址(選擇晶片/暫存器位址), 指令, 資料長度...等等, 這一部份是完全由 salve 晶片制定, master 想要控制 slave 動作必需完全依據 slave 晶片 datasheet 上的規範.

好了, 實例資料現下沒有時間整理, 以後整理好了再補充.

再談 Daisy-Chain


(2019/01/27 補充) 下二張圖是 SPI Daisy-Chain 部份的接線圖及其時序圖. 其中 SPI Master (MCU) 串接了二顆 Slave 晶片, Slave 晶片的指令/資料格式為 16 bits. 接線圖上我們標示了 ➀ ➁ 二個點, 就是後面時序圖的量測點. 時序圖中的 (DOUTM)DINS1 是 SPI Master (MCU) 的 MOSI 及 Slave1 的 MOSI (DIN) 輸入接腳連線上的時序 (接線圖上點 ➀ 所量測到的訊號), (DOUTS1)DINS2 是 Slave1 的 MISO (DOUT) 輸出接腳和 Slave2 的 MOSI (DIN) 輸入接腳連線上的時序 (接線圖上點 ➁ 所量測到的訊號).

SPI Daisy Chain 2 Slave

SPI Daisy-Chain 連接 2 顆 slave 晶片

SPI Daisy Chain Timing Chart

SPI Daisy-Chain 時序圖
(2顆 slave, data 16 bits)

如前面說的 Slave 晶片的指令/資料格式為 16 bits, 所以時序圖上的 Byte1 及 Byte2 二個合起來才是一組 16 bits 的 SPI 指令/資料. Byte3 及 Byte4 則是另一組. 由於 SPI 的電路結構使用的是串列位移暫存器, 所以我們其實可以把 Slave1 和 Slave2 合起來看, 變成一個長度為 32 bits 的串列位移暫存器 (點 ➀ 的時序圖). 由 Slave1 的觀點來看: 前 16 bits 資料 ( Byte1 及 Byte2) 當然是先把自己的串列位移暫存器填滿, 可是 Master 又接著送 Byte3 及 Byte4 進來, 所以先前的 Byte1 及 Byte2 就又都被擠出去給 Slave2 了. 由 Slave2 的觀點來看: 狀況看 Slave1 是一樣的, 只不過前 16 bits 是原先 Slave1 肚子裡的垃圾, 後 16 bits 才是由 Master 送來的 Byte1 及 Byte2.

所以 Master 送完 4 bytes 資料時, Slave1 收到了後二個 bytes, Slave2 收到了前二個 bytes. 接著 /SS 接腳訊號向上拉, Slave1 和 Slave2 一起把資料栓鎖, 開始解碼及相關動作.

總結 SPI Daisy-Chain 的注意事項有三:

  1. 傳輸時, 給遠端晶片 (離 MCU 的 MOSI 接腳比較遠的, 即 Slave2) 的資料要先送 (Byte1 及 Byte2), 再接著送給近端 (Slave1) 的資料 (Byte3 及 Byte4).
  2. 每一次傳輸都必需是完整的 N 組晶片所需的指令/資料 (N 為 Chain 裡的 slave 晶片數, 圖示為 N=2), 否則遠端晶片會收到別人的資料 (上一次傳輸所送出的資料), 產生不正確的動作.
  3. 還有一個狀況是除非晶片有支援 NOP (no operation) 的指令, 否則無法只針對 chain 裡其中一顆晶片下達指令/資料 (原因如上一項所述). 例如: 74HC595 就沒有 NOP 指令; 但是 MAX 7219/7221 就有 NOP 指令可用.

連結


SPI 參考文件

I2C 的部份請參看:

arrow
arrow

    MagicJackTing 發表在 痞客邦 留言(39) 人氣()