ESP8266開發之旅 基礎篇⑤ ESP8266 SPI通訊和I2C通訊

    設備與設備之間的通訊每每都伴隨着總線的使用,而用得比較多的就當屬於SPI總線和I2C總線,而恰巧NodeMcu也支持這兩種總線通訊,因此本章的主要內容就是講解ESP8266 SPI和I2C總線的使用。node

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

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

1.1 SPI總線概述

    SPI的通訊原理很簡單,它是全雙工主從通訊方式,這種模式下一般有一個主設備和一個或者多個從設備(注意,同一時刻,只有一個主設備和一個從設備進行通訊),須要至少4根線,特殊狀況下(單向傳輸時)3根線也能夠。
    SPI的器件工做在SPI規定下的兩種基本模式,即SPI主模式和SPI從模式。在一個SPI設備中,一般有以下表的幾個引腳:函數

引腳名稱 引腳說明
MISO(Master In Slave Out) 主設備數據輸入,從設備數據輸出
MOSI(Master Out Slave In) 主設備數據輸出,從設備數據輸入
SCK(Serial Clock) 用於通訊同步的時鐘信號,該時鐘信號由主機產生
SS(Slave Select)或CS(Chip Select) 從設備片選使能信號,由主設備控制

    主設備負責啓動通訊,負責輸出時鐘信號以及選擇通訊的從設備。當有多個從設備的時候,由於每一個從設備上都有一個CS引腳接入到主設備中,當咱們主設備和某個從設備通訊時將須要將從設備的CS引腳電平設置爲低電平或者高電平(根據實際狀況而定)。數據的收發經過MISO和MOSI進行。ui

1.2 NodeMcu SPI

    在上一章中,筆者提供的NodeMcu引腳映射圖,其實已經標註了SPI,讀者能夠查閱第2章。
    NodeMcu的SPI(注意與HSPI區分)引腳(SD0-SD三、CLK、CMD)專門用於與ESP-12E的外接flash芯片進行Quad-SPI通訊,所以不能用於SPI應用。基於ESP8266的NodeMcu具備HSPI,具備4個可用於SPI通訊的引腳(GPIO12-GPIO15)。經過這個SPI接口,咱們能夠將任何支持SPI的設備與NodeMcu鏈接起來,並與其進行通訊。下圖顯示NodeMcu的SPI部分:
image編碼

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

    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的優先級是最高的。在此,筆者不建議這麼用。ip

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設置。內存

位數 名字 描述
7 SPIE 置爲1時,表示enable SPI的中斷。
6 SPE 置爲1時,表示enable SPI。
5 DORD 發送數據時,設置爲1表示最低有效位,0表示最高有效位。
4 MSTR 設置爲1表示Arduino爲master模式,0爲slave模式。
3 CPOL 即SPI空閒時,時鐘信號SCLK的電平(1是空閒時高電平,0是空閒時低電平)。
2 CPHA 即SPI在SCLK第幾個邊沿開始採樣(0是第一個邊沿開始,1是第二個邊沿開始)。
1 SPR1 設置SPI的速度,和SPR0組合
0 SPR0 設置SPI的速度,和SPR1組合,00是最快的(4MHz),11是最慢的(250KHz)。
相關文章
相關標籤/搜索