ESP8266 SPI通信


設備與設備之間的通信往往都伴隨着總線的使用,而用得比較多的就當屬於SPI總線和I2C總線,而恰巧NodeMcu也支持這兩種總線通信

1. SPI總線——SPI類庫的使用

SPI是串行外設接口(Serial Peripheral Interface)的縮寫。是Motorola公司推出的一種同步串行接口技術,是一種高速的、全雙工、同步的通信總線。通過它可以連接使用同樣接口的外部設備。例如,ESP8266模組上,ESP8266EX芯片就是通過SPI接口與外接flash芯片連接的
SPI作為一種總線通信方式,可以通過SPI接口連接多個從設備,並通過片選控制來選擇對某一設備進行連接使用。如下圖所示:

1.1 SPI總線概述

SPI的通信原理很簡單,它是全雙工主從通信方式,這種模式下通常有一個主設備和一個或者多個從設備(注意,同一時刻,只有一個主設備和一個從設備進行通信),需要至少4根線,特殊情況下(單向傳輸時)3根線也可以。

SPI的器件工作在SPI規定下的兩種基本模式,即SPI主模式和SPI從模式。在一個SPI設備中,通常有如下表的幾個引腳:

主設備負責啟動通信,負責輸出時鍾信號以及選擇通信的從設備。當有多個從設備的時候,因為每個從設備上都有一個CS引腳接入到主設備中,當我們主設備和某個從設備通信時將需要將從設備的CS引腳電平設置為低電平或者高電平(根據實際情況而定)。數據的收發通過MISO和MOSI進行

1.2 NodeMcu SPI

NodeMcu的SPI(注意與HSPI區分)引腳(SD0-SD3、CLK、CMD)專門用於與ESP-12E的外接flash芯片進行Quad-SPI通信,因此不能用於SPI應用。

基於ESP8266的NodeMcu具有HSPI,具有4個可用於SPI通信的引腳(GPIO12-GPIO15)。通過這個SPI接口,我們可以將任何支持SPI的設備與NodeMcu連接起來,並與其進行通信

知識擴展——標准SPI、Dual SPI和Quad-SPI

    1.標准SPI
    標准SPI通常就叫做SPI,它是一種串行外設接口規范,有4根引腳信號:clk、cs、mosi、miso;
    2.Dual SPI
    它只是針對SPI Flash而言,不是針對所有SPI外設。對於SPI Flash,全雙工並不常用,因此擴展了mosi和miso的用法,讓它們工作在半雙工,用以加倍數據傳輸。也就是對於Dual SPI Flash,可以發送一個命令字節進入dual mode,這樣mosi變成SIO0(serial io 0),mosi變成SIO1(serial io 1),這樣一個時鍾周期內就能傳輸2個bit數據,加倍了數據傳輸;
    3.Quad SPI
    與Dual SPI類似,也是針對SPI Flash,Quad SPI Flash增加了兩根I/O線(SIO2,SIO3),目的是一個時鍾內傳輸4個bit。所以可以理解為:在傳輸速度上,Quad SPI=2Dual SPI=4SPI。
所以對於SPI Flash,有標准spi flash,dual spi , quad spi 三種類型,分別對應3-wire, 4-wire, 6-wire,在相同clock下,線數越多,傳輸速率越高。
    溫馨提示
    讀者可以自行了解一下NodeMcu的flash是什么標准。說不定燒錄代碼失敗就是因為這個原因(Flash模式是QIO或者DIO)

1.3 ESP8266 SPI類庫成員函數

 Arduino Core For ESP8266的SPI類庫定義在SPI.h頭文件中。該類庫只提供了作為SPI主設備的API,其成員函數如下:

1.begin()
    該功能用於初始化SPI通信。
    語法:SPI.begin()
    參數:無;
    返回值: 無;

2.end()
    該功能用於關閉SPI通信。
    語法:SPI.end()
    參數:無;
    返回值: 無;

3.setBitOrder()
    設置數據傳輸順序。
    語法:SPI.setBitOrder(order)
    參數:
        order,傳輸順序,取值為:
        ~ LSBFIRST,低位在前;
        ~ MSBFIRST,高位在前。
    返回值: 無;

4.setClockDivider()
    設置通信時鍾。時鍾信號由主機產生,從機不用配置。但主機的SPI時鍾頻率應該在從機允許的處理速度范圍內。
    語法:SPI.setClockDivider(divider)
    參數:
        divider,SPI通信的時鍾是由系統時鍾分頻得到的。可使用的分頻配置為:
        ~ SPI_CLOCK_DIV2,2分頻;
        ~ SPI_CLOCK_DIV4,4分頻(默認配置);
        ~ SPI_CLOCK_DIV8,8分頻;
        ~ SPI_CLOCK_DIV16,16分頻;
        ~ SPI_CLOCK_DIV32,32分頻;
        ~ SPI_CLOC K_DIV64,64分頻;
        ~ SPI_CLOCK_DIV128,128分頻;
    返回值: 無;

5.setDataMode()
    該功能用於設置數據模式。
    語法:SPI.setDataMode(mode)
    參數:
        mode,可配置的模式,包括:
        ~ SPI_MODE0;
        ~ SPI_MODE1;
        ~ SPI_MODE2;
        ~ SPI_MODE3;
    返回值: 無;
    注意點:
    SPI四種模式中,SPI的相位(CPHA)和極性(CPOL)分別可以為0或者1,對應的4種組合構成了4種模式:
    ~ SPI_MODE0:CPOL=0,CPHA=0;
    ~ SPI_MODE1:CPOL=0,CPHA=1;
    ~ SPI_MODE2:CPOL=1,CPHA=0;
    ~ SPI_MODE3:CPOL=1,CPHA=1;
    時鍾極性CPOL:即SPI空閑時,時鍾信號SCLK的電平(1是空閑時高電平,0是空閑時低電平)。
    時鍾相位CPHA:即SPI在SCLK第幾個邊沿開始采樣(0是第一個邊沿開始,1是第二個邊沿開始)

6.transfer()
    該功能用於傳輸1B的數據,參數為發送的數據,返回值為接收到的數據。SPI是全雙工通信,因此每發送1B的數據,也會接收到1B的數據。
    語法:SPI.transfer(val)
    參數:
        val,要發送的字節數據。
    返回值: 從機返回的1B數據;

7.transfer16()
    該功能用於傳輸2B的數據,參數為發送的數據,返回值為接收到的數據。
    語法:SPI.transfer16(val)
    參數:
        val,要發送的16位(uint16_t)數據。
    返回值: 從機返回的2B數據;
    注意點: 發送的uint16_t數據,其實底層也是分開兩個字節分別發送兩次,接收到的2B數據,也會重新組裝成uint16_t數據;

8.transferBuf()
    該功能用於傳輸一個緩沖區數據,參數為發送的緩沖區buf。
    語法:SPI.transfer(buf,count)
    參數:
        buf,要發送的緩沖區(uint8_t*)數據。
        count,緩沖區的大小。
    返回值: 無;
    注意點: 雖然沒有返回值,但是從從機傳輸回來的數據會替換掉buf緩沖區的數據,所以調用完整個方法之后,buf里面的數據就是從機返回的數據;

9.pins()
    該功能用於切換SPI引腳映射,需要在SPI.begin()之前調用SPI.pins(6,7,8,0)。
    語法:SPI.pins(sck, miso, mosi, ss)
    參數:
        sck,時鍾引腳,固定為6;
        miso,主設備輸入,從設備輸出引腳,固定為7;
        mosi,主設備輸出,從設備輸入,固定為8;
        ss,使能信號引腳,固定為0。
    返回值: 無;

注意點: 通常情況下,ESP8266的SPI對應引腳為MOSI-GPIO13,MISO-GPIO12,SCLK-GPIO14,SS-GPIO15。如果在調用SPI.begin()之前調用SPI.pins(6,7,8,0),那么引腳映射就會變成MOSI-SD1,MISO-SD0,SCLK-CLK,HWCS-GPIO0。可以看出它們和ESP8266模塊的外接Flash共享了SPI引腳。這個時候SPI的SS控制位就不是由我們的代碼來控制,而是由系統硬件本身來調配,因為它必須確保外接Flash的優先級是最高的。在此,筆者不建議這么用

1.4 SPI寄存器

所有的SPI設置都由Arduino SPI控制寄存器(SPCR)來決定。這個寄存器就是微控制器內存的一個字節,它是可讀寫的。寄存器提供的服務通常有3類:控制、數據和狀態。
    控制寄存器(SPCR)
    編碼設置控制多種微控制器的功能。通常控制寄存器中的一個位影響某個特定的設置(學過單片機系統的讀者應該比較了解這個,比如中斷允許控制寄存器IE、中斷優先級控制寄存器IP、定時器/計數器控制寄存器TCON等)。
    數據寄存器(SPDR)
    存儲數據的寄存器,比如串行口鎖存器SBUF,僅僅hold住了一個字節。比如,SPI數據寄存器hold住了要發往MOSI線的一個字節,或者這個數據是要從MISO線傳入的。
    狀態寄存器(SPSR)
    根據多種微控制器的條件改變其狀態。比如,SPI狀態寄存器(SPSR)的第七位被設置為1表示有數據從SPI傳入或傳出。
    在這里,我們主要講解一下SPI控制寄存器(SPCR),一共有8位,每一個都控制了一種特定的SPI設置

 

 

 

 

 

 

天子驕龍


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM