設備與設備之間的通訊每每都伴隨着總線的使用,而用得比較多的就當屬於SPI總線和I2C總線,而恰巧NodeMcu也支持這兩種總線通訊,因此本章的主要內容就是講解ESP8266 SPI和I2C總線的使用。node
SPI是串行外設接口(Serial Peripheral Interface)的縮寫。是Motorola公司推出的一種同步串行接口技術,是一種高速的、全雙工、同步的通訊總線。經過它能夠鏈接使用一樣接口的外部設備。例如,ESP8266模組上,ESP8266EX芯片就是經過SPI接口與外接flash芯片鏈接的。
SPI做爲一種總線通訊方式,能夠經過SPI接口鏈接多個從設備,並經過片選控制來選擇對某一設備進行鏈接使用。以下圖所示:
ide
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
在上一章中,筆者提供的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部分:
編碼
知識擴展——標準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)。接口
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
全部的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)。 |