<button id="ssm6u"><optgroup id="ssm6u"></optgroup></button>
  • 跳轉至

    SPI總線協議

    概要

    本片教程,我們詳細的為大家講解SPI總線協議。

    什么是SPI

    SPI是串行外設接口(Serial Peripheral Interface)的縮寫。是 Motorola 公司推出的一 種同步串行接口技術,是一種高速的,全雙工,同步的通信總線。SPI協議主要用于短距離的通信系統中,特別是嵌入式系統,很多芯片的外圍設備,比如LED顯示驅動器、I/O接口芯片、UART收發器等都廣泛的采用SPI總線協議。

    通信原理

    SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多
    個從設備。在英文中,通常把主設備稱作為 Master, 從設備稱作為 Slave.

    物理接線

    SPI理論上需要4根線才能進行雙向數據傳輸,3根線可以進行單向傳輸:
    SPI理論上的4根接線分別是以下四種:

    功能編號 縮寫含義 中文含義
    SDO 或者叫 MOSI Master Output Slave Input 主設備數據輸出,從設備數據輸入
    SDI 或者叫 MISO Master Input Slave Output 主設備數據輸入,從設備數據輸出
    SCLK serial clock 時鐘信號, 由主設備產生
    CS 或者叫SS chip select 片選信號, 從設備使能信號,由主設備控制。

    為了讓大家深刻理解這種主從的模式,我們1Z實驗室做出了下圖方便大家理解。

    img

    PS: 把上面這兩張圖 重新做一下吧

    起始、停止信號

    如上圖,紅色編號1和6即為起始和停止信號的發生區域。

    CS片選信號(圖中的NSS)電平由高變低,則產生起始信號;

    CS片選信號電平由低變高,則產生停止信號。

    從機檢測到自己的CS片選信號線電平被置低,則開始與主機進行通訊;

    反之,檢測到NSS電平被拉高,則停止通訊。

    數據有效性

    MOSI和MISO線在SCK的每個時鐘周期傳輸一位數據,開發者可以自行設置MSB或LSB先行,不過需要保證兩個通訊設備都使用同樣的協定。

    從以下的時序圖可以看出,在SCK時鐘周期的上升沿和下降沿時進行觸發和采樣。

    這里的觸發和采樣其實是兩個特殊的時間節點,分別對應了SCK時鐘周期的上升沿和下降沿。

    SPI有四種通訊模式,在SCK上升沿觸發,下降沿采樣只是其中一種模式。四種模式的主要區別便是總線空閑時SCK的狀態及數據采樣時刻。這涉及到“時鐘極性CPOL”和“時鐘相位CPHA”,由CPOL和CPHA的組合而產生了四種的通訊模式。

    • CPOL:即在沒有數據傳輸時,時鐘的空閑狀態的電平。上面的兩幅圖示中,無數據傳輸時的時鐘空閑狀態為低電平。

    • CPHA:即數據的采樣時刻,可以是SCK的上升沿,也可以是SCK的下降沿。

    如果我們將CPOL和CPHA的兩種狀態分別用0,1表示,因此由這兩種方式排列組合,便可以產生四種模式的SPI:

    SPI模式 CPOL 空閑時SCK時鐘 CPHA 采樣時刻
    0 0 低電平 0 SCK下降沿
    1 0 低電平 1 SCK上升沿
    2 1 高電平 0 SCK下降沿
    3 1 高電平 1 SCK上升沿

    配合下圖,你可以仔細揣摩一番:

    很重要的一點是,主機和從機需要工作在相同的模式下才能正常通訊

    SPI優點

    • 支持全雙工通信,發送數據和接收數據可以同時進行。

    • 通信簡單

    • 數據傳輸速率快

    SPI缺點

    • 接線繁雜,需要至少四根接線

    • 在多個從機的情況下,每個從機都需要接入一根CS片選信號線,這是十分的浪費芯片的IO資源

    硬件資源

    NodeMCU-32S擁有兩組硬件SPI總線資源, 分別是HSPI和VSPI,所對應的引腳如下圖:

    ValueError: SPI ID must be either HSPI(1) or VSPI(2)

    為方便大家接線,貼出下表:

    SPI組號 MOSI MISO CS LCK
    VSPI GPIO 23 GPIO 19 GPIO 5 GPIO 18
    HSPI GPIO 13 GPIO 12 GPIO 15 GPIO14

    除此兩組SPI硬件資源外,其余的GPIO理論上也可以配置成SPI總線的輸入輸出管腳,只要滿足該管腳既能夠作為輸入也能夠作為輸出。因此,在MicroPython中,我們擁有兩種模式的SPI總線,即:

    • 硬件SPI

    • 軟件SPI (GPIO模擬)

    SPI API文檔

    硬件SPI構造

    上文我們為大家羅列出了兩組硬件SPI,構造他們很簡單:

    以下是HSPI的構造:

    >>> from machine import SPI
    >>> hspi = SPI(1)
    >>> hspi
    SPI(id=1, baudrate=500000, polarity=0, phase=0, bits=8, firstbit=0, sck=-1, mosi=-1, miso=-1)
    >>> 
    

    以下是VSPI的構造:

    >>> from machine import SPI
    >>> vspi = SPI(2)
    >>> vspi
    SPI(id=1, baudrate=500000, polarity=0, phase=0, bits=8, firstbit=0, sck=-1, mosi=-1, miso=-1)
    >>> 
    

    注意

    你可能會發現無法同時構造兩個硬件SPI,即使你認為這么做并不該出錯。

    然而MicroPython并不允許你這樣做,hspi和vspi只能存在一個,不能一起使用。

    軟件SPI構造

    軟件SPI構造較為硬件要傳入的參數比較繁多,有兩種構造方法:使用類構造或使用init函數構造

    類構造

    SPI(baudrate, polarity, phase, bits, firtbit, sck, mosi, miso)

    • baudrate:SCK時鐘頻率 范圍 0 < baudrate ≤ 0x0FFFFFFF (十進制:0 < baudrate ≤ 2147483647)

    • polarity:極性

    • 0 時鐘空閑時候的電平是低電平,所以當SCLK有效的時候,就是高電平

    • 1 時鐘空閑時候的電平是高電平,所以當SCLK有效的時候,就是低電平

    • phase:相位

    • 0 在第一時鐘沿采樣數據

    • 1 在第二時鐘沿采樣數據

    • bits:傳輸數據位數

    • firtbit:數據傳輸的第一位(高位或低位)

    • sck 時鐘信號引腳

    • mosi 主設備輸出,從設備輸入引腳

    • miso 主設備輸入,從設備輸出引腳

    ? Pin(0)、Pin(2)、Pin(4)、Pin(5)、Pin(9)、Pin(16~19)、Pin(21~23)、Pin(25~27)

    示例:

    from machine import SPI, Pin
    
    spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(17), mosi=Pin(27), miso=Pin(18))
    

    使用init函數構造

    SPI.init(baudrate, polarity, phase, sck, mosi, miso)

    函數說明:初始化SPI總線
    參數含義同上文類構造一致

    示例:

    spi = SPI.init(baudrate=100000, polarity=1, phase=0, sck=Pin(17), mosi=Pin(27), miso=Pin(18))
    

    寫數據

    SPI.write(buf)

    函數說明:將 buf 中的所有數據寫入到總線。
    示例:

    buf = bytearray([1,2,3,4,5,6,7,8])
    spi.write(buf)
    

    讀數據

    SPI.read(len, data=0x00)

    函數說明:讀取len個數據的同時寫入len個data數據,以數組的形式返回讀取到的數據。

    len: 需要讀取的字節長度
    data: 寫入的單字節數據

    示例:

    buf=bytearray(2) #申請長度為2的緩沖區
    buf = spi.read(2, 0x00)
    

    SPI.readinto(buf, data=0x00)

    函數說明:讀取buf.len個數據并存入buf中,同時寫入buf.len個data數據,函數返回None。

    buf: 數據緩沖區
    data: 寫入的單字節數據

    SPI.write_readinto(write_buf, read_buf)

    函數說明:寫入write_buf并讀取到 read_buf,寫入并讀取的長度為buf長度,要求兩個緩沖區長度相同。

    write_buf: 寫數據緩沖區
    read_buf: 讀數據緩沖區

    示例:

    write_buf = bytearray([1, 2, 3, 4, 5, 6, 7, 8])
    read_buf = bytearray(8)
    spi.write_readinto (write_buf, read_buf)
    print(read_buf)
    

    釋放資源

    SPI.deinit()

    函數說明:關閉SPI。
    示例:

    spi.deinit()
    

    • SPI.MSB = 0 從一個字節中的最高位依次到最低位開始發送該字節數據

    • SPI.LSB = 1 從一個字節中的最低位依次到最高位開始發送該字節數據

    綜合示例

    todo


    韩国精品无码一区二区三区,精品无码一区二区三区AV,欧洲丰满美熟女乱又伦AV,亚洲午夜久久久影院伊人