何謂串列週邊介面(SPI) ? 關於 SPI 通訊的介紹
步驟與項目
何謂串列週邊介面(SPI) ? 關於 SPI 通訊的介紹
串列週邊介面(SPI)是一種介面匯流排,常用於微控制器和小型外設之間傳送數據,如移位寄存器、感測器和SD卡。它使用獨立的時鐘和數據線,以及一個選擇線,用於選擇您想要通信的設備。
串行端口存在一些問題
串行端口存在的問題在於它們是「非同步」的,這意味著沒有對數據何時發送進行控制,也沒有保證雙方以完全相同的速率運行。由於計算機通常依賴於所有事物都與單一的“時鐘”同步(即連接到計算機的主晶體驅動的一切),因此當兩個具有略微不同時鐘的系統試圖相互通信時,這可能是個問題。
為了解決這個問題,非同步串行連接在每個字節中添加了額外的起始位和停止位,幫助接收器在數據到達時進行同步。雙方還必須事先就傳輸速率(例如每秒9600位)達成一致。傳輸速率的輕微差異並不是問題,因為接收器在每個字節的開始時重新進行同步。
這段提到的細節確實很值得稱讚!串行協議通常會先發送最低有效位,因此最小的位數位於最左邊。因此,較低的四位元實際上是 0011(0x3),而較高的四位元是 0101(0x5)。
非同步串行通訊運作得很好,但在每個字節中發送的額外起始和停止位以及發送和接收數據所需的複雜硬件都存在較大的開銷。而且,如您在自己的項目中可能已經注意到的那樣,如果兩端的速率不相同,接收到的數據將會是垃圾。這是因為接收器在非常特定的時間(上述圖中的箭頭)取樣位元。如果接收器在錯誤的時間取樣,它將看到錯誤的位元。
A Synchronous Solution 同步解決方案
SPI 以稍微不同的方式工作。它是一種「同步」數據匯流排,這意味著它使用獨立的數據線和一個「時鐘」來保持雙方完美同步。時鐘是一個振盪信號,告訴接收器何時在數據線上取樣位元。這可以是時鐘信號的上升(低到高)邊緣或下降(高到低)邊緣;數據表將指定使用哪一種。當接收器檢測到該邊緣時,它將立即查看數據線以讀取下一位(見下圖中的箭頭)。由於時鐘與數據一起傳送,因此指定速度並不重要,盡管設備將具有其可以運行的最高速度(稍後我們將討論如何選擇適當的時鐘邊緣和速度)。
SPI 如此受歡迎的一個原因是,接收硬體可以是一個簡單的移位寄存器。這是一個比非同步串行所需的完整 UART(通用非同步收發器/傳輸器)要簡單(且更便宜!)的硬體。
Receiving Data 接收資料
您可能會想自問:這對單向通訊很好,但如何在相反的方向上發送資料呢?這裡的情況稍微複雜一些。
在 SPI 中,只有一方產生時鐘信號(通常稱為 CLK 或 SCK,表示串行時鐘)。產生時鐘信號的一方稱為「控制器」,而另一方稱為「周邊設備」。通常只有一個控制器(幾乎總是您的微控制器),但可以有多個周邊設備(稍後會詳細介紹)。
當資料從控制器發送到周邊設備時,它會通過一條名為 PICO 的資料線發送,即「周邊設備輸入/控制器輸出」。如果周邊設備需要將回應發送回控制器,則控制器將繼續產生一定數量的時鐘周期,而周邊設備則會將資料放到第三條名為 POCI 的資料線上,即「周邊設備輸出/控制器輸入」。
請注意我們在上面的描述中提到了「事先安排」。由於控制器始終生成時鐘信號,它必須事先知道何時周邊設備需要返回資料,以及將返回多少資料。這與非同步串行非常不同,因為在非同步串行中,可以隨時以任意量的資料在任何方向上進行傳送。實際上,這並不是問題,因為 SPI 通常用於與具有非常特定命令結構的感測器進行通信。例如,如果您向設備發送「讀取資料」的命令,則知道設備將始終返回例如兩個位元組的資料。(在可能需要返回可變量的資料的情況下,您始終可以返回一個或兩個位元組來指定資料的長度,然後讓控制器檢索全部資料。)
請注意,SPI 是「全雙工」的(具有獨立的發送和接收線),因此在某些情況下,您可以同時傳送和接收資料(例如,在檢索先前資料的同時,請求新的感測器讀取)。您的設備資料表將告訴您這是否可能。
您還應該了解最後一條線,稱為晶片選擇(Chip Select,CS)。這告訴周邊設備它應該喚醒並接收/發送資料,當存在多個周邊設備時,也用於選擇您想要通信的那一個。
在 SPI 中的晶片選擇 CS 線通常保持高電位,這將周邊設備與 SPI 匯流排斷開連接。(這種邏輯稱為“主動低”,您通常會看到它用於啟用和重置線。)在將資料發送到周邊設備之前,將該線拉低,這將激活周邊設備。當您完成使用周邊設備時,該線再次拉高。在移位寄存器中,這對應於“鎖存器”輸入,它將接收到的資料傳輸到輸出線。
Multiple Peripherals 多種周邊
連接多個周邊設備到一個 SPI 匯流排有兩種方式:
一般來說,每個周邊設備都需要一條獨立的 CS 線。要與特定的周邊設備通信,您會將該設備的 CS 線拉低,並保持其他設備的 CS 線保持高電位(您不希望同時啟動兩個周邊設備,否則它們可能會嘗試在同一條 POCI 線上進行通信,導致資料錯亂)。許多周邊設備將需要許多 CS 線;如果您的輸出端口不夠,可以使用二進製解碼器芯片來增加 CS 輸出。
另一方面,有些部件更喜歡被串聯在一起,其中一個設備的 POCI(輸出)連接到下一個設備的 PICO(輸入)。在這種情況下,單個 CS 線連接到所有周邊設備。一旦所有資料發送完畢,CS 線被拉高,導致所有晶片同時啟動。這通常用於串聯移位寄存器和可寫入地址的 LED 驅動器。
請注意,對於這種佈局,資料會從一個周邊設備溢出到下一個設備,因此要向任何一個周邊設備發送資料,您需要發送足夠的資料以覆蓋所有設備。同時請記住,您發送的第一個資料將最終傳送到最後一個周邊設備。
這種佈局類型通常用於僅輸出的情況,例如驅動 LED,您不需要接收任何資料。在這些情況下,您可以將控制器的 POCI 線斷開。但是,如果需要將資料返回到控制器,可以通過關閉串聯環路(上述示意圖中的藍線)來實現。請注意,如果這樣做,周邊設備 1 的返回資料將需要通過所有周邊設備才能返回到控制器,因此請確保發送足夠的接收命令以獲取所需的資料。
SPI 程式設計
許多微控制器都具有內建的 SPI 周邊設備,可以處理發送和接收資料的所有細節,並且可以以非常高的速度進行。SPI 協議也足夠簡單,您(是的,就是您!)可以編寫自己的程式例程,以正確的順序操作 I/O 線以傳輸資料。(在維基百科的 SPI 頁面上有一個很好的範例。)
如果您正在使用 Arduino,有兩種方法可以與 SPI 設備通信:
- 您可以使用 shiftIn() 和 shiftOut() 命令。這些是基於軟體的命令,可以在任何一組引腳上運行,但速度較慢。
- 或者您可以使用 SPI Library,該庫利用了微控制器內建的 SPI 硬體。這比上述命令快得多,但只能在特定的引腳上使用。
發佈留言
很抱歉,必須登入網站才能發佈留言。