No Code AI(肉寇)AI自動化兩日精通|實體6小時+線上6小時
|
View Categories

SPI 界面解密 — PART 4

閱讀時間: 4 min read

作者:Bird

上篇文章【Maker電子學】SPI 界面解密—PART 3,我們詳細說明了 SPI 工作時的波形,以及它的各種變化,這次我們要用一個實際的例子來看看週邊裝置如何透過 SPI 與 MCU 溝通。

MCP3008 #

我們要拿來當作範例的 SPI 週邊,是一顆叫做 MCP3008 的 10-bit 類比數位轉換晶片(A/D converter)。這顆 ADC 晶片是 Microchip 的產品,由於它很容易使用,速度也不差,常用在 Raspberry Pi 上作爲類比訊號的輸入界面,用以彌補 Raspberry Pi 先天沒有類比輸入界面的遺憾。

MCP3008(Source

我們先簡單來看一下 MCP3008 的規格。它有 8 個 channel 的輸入(但是同時只能選一個來用)、在 5 V 供電的情況下可以達到最快 200 K samples/sec 的取樣及轉換速度、10-bit 的解析度、以及最大 +/-1 LSB 的非線性。

關於它的轉換速度,我們來看看它的 datasheet:

(圖片來源:Bird 提供)

在 VDD = 5 V 時,最快可以到 200 Ksps,也就是每秒做 20 萬次取樣、轉換;VDD= 3.3 V 時它的動作會慢一點,只能跑到 75 Ksps。重點來了,它的取樣時間是 1.5 個 clock cycles,轉換時間是 10 個 clock cycles,但是 MCP3008 的電路中其實並沒有外加的 clock source,那麼這裡的 clock cycle 指的到底是什麼 clock 呢?

MCP3008 是所謂的「同步轉換型 ADC」,它的轉換動作與界面的動作是同步綁在一起的,因此這裡 conversion time 的 10 clock cycles,其實指的就是 SPI 上的 10 個 clock;換句話所,MCP3008 的 A/D 轉換速度完全由 SPI 界面的速度來控制。

訊號與連接 #

MCP3008 使用的是四線式的 SPI,但它的訊號命名與我們之前介紹的有點不同。它的 MOSI 叫做 DIN(data in 的意思)、MISO 稱為 DOUT、Slave select 叫做 CS(意思是 chip select),一樣是低電位動作。

MCU 與 MCP3008 的 SPI 連接如下圖:

(圖片來源:Bird 提供)

爲了避免混肴,以下介紹時序都用 MCP3008 的訊號命名。

時脈圖中的細節 #

我們來看一下 MCP3008 的 SPI 時脈圖和轉換的關係吧!

(圖片來源:Bird 提供)

先看 DIN 與 CLK 的關係。從圖中可以看出來,每個 bit 都是在 CLK 的上升緣取樣,接著再看 CS 與 CLK 的關係,我們第一個有效的資料位元 start bit 在 CS 下降後的第一個 CLK 變化瞬間取樣,因此我們可以知道這個 SPI 的時序是:

  • CPHA = 0
  • CPOL = 0

事實上這也是四線式 SPI 最常見的時序(如果不清楚 CPHA 和 CPOL 是什麼,趕快翻一下上一篇文章複習一下唷!)。

接下來要來看控制訊號的輸入和轉換資料的輸出。當 CS 下來到 low,會叫醒 MCP3008 請它準備工作時,第一個透過 DIN 送過去的 bit 就是 start bit,這是個固定爲 1 的 bit,用意也是叫 MCP3008 準備開始工作,但明明前面 CS 訊號已經叫它準備開工了,爲什麼還要多一個 start bit 呢?這跟 SPI 的非典型時序有關(這裡先賣個關子,後面會解釋)。

緊接著 start bit 後,是四個 bit 的控制訊號,其中包含一個 bit 的 SGL/DIFF,用來控制 MCP3008 是要用單端(single-end)還是差動(differential)模式輸入。其實 MCP3008 可以將相鄰的兩個輸入當作一組差動輸入來用,而它的極性(也就是誰正誰負)也是可以設定的,另外有三個 bit 的 channel number,是用來選擇使用哪一個輸入的。

MCP3008 總共有 8 個輸入, single-end 模式下 8 個輸入可以任意選擇,而在 differential 模式下,則是相鄰的兩個輸入爲一組,總共有 4 組可以選,每一組又有正反兩種極性,所以也是 8 個組合,剛好用 3 個 bit:D0、D1、D2 來設定。

包含 start bit 及 4 個 bit 的控制訊號從 DIN 送入 MCP3008 後,DIN 就功成身退了,之後雖然 clock 訊號會繼續跑,但 MCP3008 不會再從 DIN 上讀取任何資料。

接著,從第 5 個 clock 的後半以及下一個 clock,也就是 CS 下降後的第 6 個 clock,MCP3008 會對設定的輸入做取樣。「取樣」是數位訊號處理上很特殊的一個概念,它的意思是 MCP3008 這一次的轉換,所取的就是現在這個 moment 所指定輸入上的狀態;換句話說,在第 5 個 clock 後半及第 6 個 clock 的這段時間,選定輸入 channel 上的電壓後,一會就會被轉換成數字,從 SPI 上被送出去。

我們前面說過,MCP3008 的 tSAMPLE(也就是取樣時間)需要 1.5 個 clock,事實上指的就是 SPI 的第 5 個 clock 後半段以及第 6 個 clock;雖然整體轉換、讀出的時間長達十多個 clock cycle,但我們讀到的,就是這短短 1.5 個 clock 中的狀態。

接著,clock 繼續跑,DOUT 上會開始吐出資料。首先會先吐出一個無關緊要的 bit,稱之爲 null bit,它沒有任何意義,接下來就會是 10 個 bits 的轉換資料,會先從 MSB 開始,B9、B8、B7 依序一直到 B0。在讀取 B0 的那個 clock 結束後,CS 會上升,結束這 1+4+1+1+10 共 17 個 clock 的轉換週期,讓一切歸於平靜。

此時,如果要繼續發起下一次轉換,CS 必需要維持至少一小段時間的 high,讓 MCP3008 休息喘口氣,才能再次變 low,開始下一個轉換週期。這段最短休息時間在圖上用 tCSH 表示,根據 datasheet 上的 timing 規格,它至少要 27 0ns,在大部分的狀況下,我們可以用一個 clock cycle 來代表它,因此可以說,MCP3008 的一次轉換週期總共需要 18 個 SPI clock cycles。

在這 18 個 clock cycles 中,總共傳了 5 個 bit 進去、10 個 bit 出來,還有 3 個沒有傳資料的 clock。

8-bit 的魔咒 #

那…我們上次不是說過,SPI 的資料傳輸都必須以 8-bit,也就是 byte 爲基本單位嗎?MCP3008 怎麼會有這種 5 個 bit、10 個 bit、18 個 bit 的傳輸週期呢?

事實上經過多年的發展,現在確實有很多週邊晶片會使用像 MCP3008 這樣,不是以 byte 爲基本單位的 SPI 傳輸,但由於大部分的 MCU 仍然遵循以 byte 爲單位的 SPI 傳輸,MCP3008 也設計了一套可以用 byte 爲單位傳輸的時序。

而這整件事情的奧祕,就在於我們前面提到,看似無用的「start bit」。

根據前面的說明,在整個 CS 爲 low 的期間,SPI 的 clock 總共動了 17 個 cycle,也就是有 17 個 data bits 在 17 個 clock 的上升緣被讀入或讀出。

爲了要讓這整件事情可以用 8 的倍數運作,我們在這 17 個 bit 前面再補 7 個 bit,讓它變成總共 17 + 7 = 24 bits,就剛好是 3 個 bytes。如此一來,就變成 CS 下降之後,我們可以用標準的 SPI 界面同時對 MCP3008 寫入和讀取 3 個 bytes(還記得嗎?SPI 因爲有 MISO 和 MOSI 兩根線各自負責讀寫,所以是全雙工的,讀和寫可以同時發生)。

(圖片來源:Bird 提供)

我們先看 DIN 上寫入 MCP3008 的資料。前面補上的 7 個 clock,DIN 全部填上 0,接著後面就跟著永遠爲 1 的 start bit 及 4 個控制 bit,再接下來的 11 個 clock,如同前面所說的,由於該寫的都寫完了,DIN 上的狀態不再重要,這裡要送什麼都無所謂。

巧妙的地方就在這裡:MCP3008 會等到收到 DIN 上的 start bit 才開始接收 control bit 並開始工作,因此在 start bit 前面補的 7 個 0 其實會被 MCP3008 完全忽略,直到第 8 個 clock(也就是 start bit),才開始照著前面說明的時序運作,這也就是前面說需要一個看似無用的 start bit 的原因。

至於 DOUT 上,我們一樣可以從 CS 被拉下來就開始讀取,連續讀 24 bits 或 3 bytes,不過 MCP3008 會一直等到第 15 個 clock 才開始吐資料出來;也就是說,它輸出的資料會位在第 15 到第 24 總共 10 個 clock 上。

我們把送出去和讀回來的這 3 個 bytes 排列一下,就可以知道要送要收的資料位在這 3 個 bytes 的哪一個 bit 了:

(圖片來源:Bird 提供)

那麼我們就可以巧妙地將資料安排在 24 個 clock 中,利用標準的 3 個 byte SPI 傳輸來控制 MCP3008 完成一次轉換。

不過其實當我們爲了遷就標準 SPI 時序這麼做時,其實我們浪費了 7 個 clock 的時間在餵沒有用的資料給 MCP3008,因此如果我們想要追求 MCP3008 的最大轉換速率,這樣無疑是在拖慢速度。

事實上由於 SPI 只是個很簡單的 shift register,如果 MCU 的 I/O 速度允許,有時候用軟體控制 GPIO 實作而成的 bit-bang SPI 不見得會比硬體的 SPI 慢,而且也不用受到 8-bit 爲一個傳輸單位的限制,可以直接實作出 17 個 clock 的傳輸週期。

小結 #

關於 SPI 的介紹,我們大概就說到這邊。SPI 只定義了傳輸的訊號該長什麼樣子,並沒有標準化的裝置地址或標準的 register number 等協定,所以其實算是個相對簡單的界面(實作的細節都藏在界面晶片的規格中,而且可能各不相同)。

下一回我們要開始來聊 I2C,它大概是我們所介紹的這三個界面中最複雜、最博大精深的一個了,我們下回見!

(責任編輯:賴佩萱)

Powered by BetterDocs

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *