來源:https://www.w3cschool.cn/arduino/arduino_serial_peripheral_interface.htmlhtml
串行外設接口(SPI)總線是用於串行通訊的系統,最多可以使用四個導體,一般爲三個。一個導體用於數據接收,一個導體用於數據發送,一個導體用於同步,另外一個導體用於選擇與之通訊的設備。它是一個全雙工鏈接,這意味着數據是同時發送和接收的。最大波特率高於I2C通訊系統中的波特率。python
SPI使用如下四條線:git
SCK - 這是由主機驅動的串行時鐘。數組
MOSI - 這是由主機驅動的主輸出/從輸入。ide
MISO - 這是由主機驅動的主輸入/從輸出。函數
SS - 這是從機選擇線。oop
使用如下函數,必須包括SPI.h.字體
SPI.begin() - 經過將SCK,MOSI和SS設置爲輸出來初始化SPI總線,將SCK和MOSI拉低,將SS拉高。ui
SPI.setClockDivider(分頻器) - 相對於系統時鐘設置SPI時鐘分頻器。在基於AVR的板上,可用的分頻器爲2,4,8,16,32,64或128。默認設置爲SPI_CLOCK_DIV4,它將SPI時鐘設置爲系統時鐘的四分之一(對於20 MHz的電路板爲5 Mhz)。lua
Divider - 它能夠是(SPI_CLOCK_DIV2,SPI_CLOCK_DIV4,SPI_CLOCK_DIV8,SPI_CLOCK_DIV16,SPI_CLOCK_DIV32,SPI_CLOCK_DIV64,SPI_CLOCK_DIV128)。
SPI.transfer(val) - SPI傳輸基於同時發送和接收:接收的數據在receivedVal中返回。
SPI.beginTransaction(SPISettings(speedMaximum,dataOrder,dataMode)) - speedMaximum是時鐘,dataOrder(MSBFIRST或LSBFIRST),dataMode(SPI_MODE0,SPI_MODE1,SPI_MODE2或SPI_MODE3)。
SPI中有四種操做模式,以下所示:
模式0(默認值) - 時鐘一般爲低電平(CPOL = 0),數據在從低電平到高電平(前沿)(CPHA = 0)的轉換時採樣。
模式1 - 時鐘一般爲低電平(CPOL = 0),數據在從高電平到低電平(後沿)(CPHA = 1)的轉換時採樣。
模式2 - 時鐘一般爲高電平(CPOL = 1),數據在從高電平到低電平(前沿)(CPHA = 0)的轉換時採樣。
模式3 - 時鐘一般爲高電平(CPOL = 1),數據在從低電平到高電平(後沿)(CPHA = 1)的轉換時採樣。
SPI.attachInterrupt(handler) - 當從設備從主設備接收數據時調用的函數。
如今,咱們將兩個Arduino UNO板鏈接在一塊兒;一個做爲主機,另外一個做爲從機。
接地是常見的。如下是兩個電路板之間的鏈接的圖示:
讓咱們看看SPI做爲主機和SPI做爲從機的例子。
#include <SPI.h> void setup (void) { Serial.begin(115200); //set baud rate to 115200 for usart digitalWrite(SS, HIGH); // disable Slave Select SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8 } void loop (void) { char c; digitalWrite(SS, LOW); // enable Slave Select // send test string for (const char * p = "Hello, world!\r" ; c = *p; p++) { SPI.transfer (c); Serial.print(c); } digitalWrite(SS, HIGH); // disable Slave Select delay(2000); }
#include <SPI.h> char buff [50]; volatile byte indx; volatile boolean process; void setup (void) { Serial.begin (115200); pinMode(MISO, OUTPUT); // have to send on master in so it set as output SPCR |= _BV(SPE); // turn on SPI in slave mode indx = 0; // buffer empty process = false; SPI.attachInterrupt(); // turn on interrupt } ISR (SPI_STC_vect) // SPI interrupt routine { byte c = SPDR; // read byte from SPI Data Register if (indx < sizeof buff) { buff [indx++] = c; // save data in the next index in the array buff if (c == '\r') //check for the end of the word process = true; } } void loop (void) { if (process) { process = false; //reset the process Serial.println (buff); //print the array on serial monitor indx= 0; //reset button to zero } }