設備間通信
兩個設備或者多個設備之間通信時,需要有一份共同遵守的協議,避免雞同鴨講。
常見的通信協議有:SPI、USB、UART、I2C、CAN[1][2]。
圖 1:不同的設備間通信協議
不同的協議是為了滿足特定場景的要求而制定的,而不是為了好玩。因此應該分析特定應用的要求,並選擇合適的協議。
SPI 協議
使用 SPI 協議的場景是全雙工、同步傳輸、一主多從、線少、高速率。
以下是使用 SPI 協議通信的設備群:
圖 2:SPI 一主多從
從圖中可以看出一對設備通過 SPI 協議進行通信需要四條線。SPI 四條線分別是:
- 片選信號線(CS,Chip Select):選設備
- 主輸出從輸入數據線(MOSI):傳數據
- 從輸出主輸入數據線(MISO):傳數據
- 時鍾信號線(SCK,Serial Clock):提供采集數據的時機
數據傳輸線
由於使用同步傳輸,所以傳輸一個字節的 8 位二進制不需要八條導線,只需要一條線分 8 個時鍾發送就行了。下文的時鍾信號線部分會再次提到。
另外由於要支持全雙工,即一次傳輸過程中主設備傳輸數據到從設備的同時,從設備也可以傳輸數據到主設備,因此需要兩條傳輸方向不同的線 MOSI(Master Out/Slave In) 和 MISO(Master In/Slave Out)。如下圖:
圖 3:全雙工。藍色線表示主設備輸出,紅色線表示從設備輸出。
從圖 3 可以看出,單向傳輸的線連接了多個從設備。
注意這里的接線方式:主設備的 MOSI 接從設備的 MOSI,主設備的 MISO 接從設備的 MISO。
此時我們有了疑問:這些從設備都會同時接收數據嗎?多個從設備同時發送數據給主設備豈不是沖突了?
片選信號線
主設備會通過控制從設備的 CS 引腳來激活從設備。上面說過從設備的 CS 引腳為低電平的時候,從設備被激活。
圖 4:片選信號線
下圖表示從設備被激活后傳輸數據(NSS 是 CS 引腳的另一個稱呼):
圖 5:拉低片選線后才開始傳輸數據
紅框部分表示持續激活從設備,以及采集數據。
注意,主設備用 I/O 線連接到從設備的片選信號線上。
時鍾信號線
時鍾信號線提供讀取數據信號的時機。時鍾信號由主設備提供給從設備。
圖 6: 時鍾信號(中間波浪線表示省略 N 個信號)
時鍾線的作用是提供高低電平的變化作為數據采樣的信號。根據不同的模式,可以是從高到低的時候采樣,也可以是從低到高的時候采樣。
SPI 協議有四種通信模式,分別由 CPOL(時鍾極性)和 CPHA(時鍾相位)來控制。也就是選擇采樣的時機。
CPOL(Clock POLarity) 表示時鍾空閑時的電平。0 為低電平,1 為高電平。如下圖表示 CPOL = 0。
圖 7:空閑的 SCK 為低電平,即 CPOL 為 0 的情況
CHPA(Clock PHAse) 表示數據有效的時刻的相位,或者說邊沿(Edge)。邊沿指的是電平變化的時刻,有兩種類型:上升沿(Rising Edge)和下降沿(Falling Edge)。0 表示處於第一個邊沿類型的時刻數據有效(進行采樣),1 表示處於第二個邊沿類型的時刻數據有效(進行采樣)。
圖 8:上升沿和下降沿
下圖標出了采樣的時機:
圖 9:工作在(0,1)模式的數據采樣
四種模式用下表列出:
SPI 通信模式 | CPOL | CPHA | 特點 |
---|---|---|---|
0 | 0 | 0 | 時鍾空閑時保持低電平,工作時在上升沿從輸入引腳采樣,在下降沿改變輸出引腳的數據 |
1 | 0 | 1 | 時鍾空閑時保持低電平,工作時在下降沿從輸入引腳采樣,在上升沿改變輸出引腳的數據 |
2 | 1 | 0 | 時鍾空閑時保持高電平,工作時在下降沿從輸入引腳采樣,在上升沿改變輸出引腳的數據 |
3 | 1 | 1 | 時鍾空閑時保持高電平,工作時在上升沿從輸入引腳采樣,在下降沿改變輸出引腳的數據 |
注:兩個通信的設備要配置為同一個模式才能正常通信。
通信雙方采樣的時機是一致的,改變輸出的時機也是一致的。不然 A 在采樣的時候,B 把輸出改了,那 A 得到的數據可能是修改前的數據也可能是修改后的數據,就亂了。
如何確保主從處於同一模式?應該以從設備的模式為准,再配置主設備的模式。從設備的模式有兩種情況[3]:
- 從設備的 SPI 模式由硬件決定,已經被固定
- 從設備有 SPI 控制器,則 SPI 模式由軟件決定,可配置
在模式相同且片選信號線拉低時,開始通信。通常芯片內部的 SPI 控制器會自動控制在 8 次取樣后停止通信,也就是一次傳輸 8 bit,即一個字節。但也可以使用 I/O 線模擬片選信號,這樣一次可以傳送多個字節[4]。
圖 10:工作在(0,1)模式的數據采樣
圖 10 中的 MSB 和 LSB 表示最高權重位(Most Significant Bit)和最低權重位(Least Significant Bit)[5]。權重指的是對這個數值影響程度高,例如十進制的萬比千的權重高。
一個字節,即 8 位二進制數據可以從最高位開始發送,也可以從最低為開始發送。
舉個例子:
一個字節的數據:1000 0000
MSB | - | - | - | - | - | - | LSB |
---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
從最高位開始發送就是先發 1。
如果通信雙方沒有達成一致,則接收者得到的數據和發送者的數據的含義不一致。不過這個通常不需要我們配置。
總結
如果要用到 SPI 協議,需要接四條線。
- 主設備的 MISO 接從設備的 MISO
- 主設備的 MOSI 接從設備的 MOSI
- 主設備的 SCK 接從設備的 SCK
- 主設備任選一個 I/O 接從設備的 CS
主設備在編程的時候需要配置與從設備相同的 SPI 模式。
主設備在編程的時候需要配置第一位(First Bit)[6]先從 MSB 開始發還是 LSB 開始發。從設備會規定第一位是 MSB 還是 LSB。
參考:
[1]: https://zhuanlan.zhihu.com/p/47925844 (常見硬件通信協議介紹)
[2]: https://blog.csdn.net/heda3/article/details/89053635 (IIC、SPI、UART、USART、USB、CAN等通訊協議原理及區別)
[3]: https://blog.csdn.net/u013165704/article/details/81076890 (SPI 接口配置)
[4]: https://blog.csdn.net/qq_25814297/article/details/86190106 (SPI通訊有單字節模式和多字節連續模式)
[5]: https://www.cnblogs.com/shuaifeng/archive/2009/12/23/1630195.html (MSB與LSB)
[6]: https://www.stmcu.org.cn/module/forum/thread-627137-1-1.html ([分享] SPI原理超詳細講解---值得一看)