Arduino - SPI 通訊
序列外設介面(SPI)匯流排是一種序列通訊系統,最多使用四根導線,通常為三根。一根導線用於資料接收,一根用於資料傳送,一根用於同步,另一根用於選擇與之通訊的裝置。它是全雙工連線,這意味著資料同時傳送和接收。最大波特率高於 I2C 通訊系統。
SPI 引腳
SPI 使用以下四條線 -
-
SCK - 這是由主機驅動的序列時鐘。
-
MOSI - 這是主機驅動的主輸出/從機輸入。
-
MISO - 這是主機驅動的主輸入/從機輸出。
-
SS - 這是從機選擇線。
使用以下函式。你必須包括 SPI.h.
-
SPI.begin()
- 通過將 SCK,MOSI 和 SS 設定為輸出,將 SCK 和 MOSI 拉低,SS 為高電平來初始化 SPI 匯流排。 -
SPI.setClockDivider(divider)
- 設定相對於系統時鐘的 SPI 時鐘分頻器。在基於 AVR 的電路板上,可用的分頻器為 2,4,8,16,32,64 或 128.預設設定為 SPI_CLOCK_DIV4,它將 SPI 時鐘設定為系統時脈頻率的四分之一(5 Mhz 用於 20 MHz 的電路板)。 -
分頻器 - 可以是(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 板連線在一起; 一個作為主機,另一個作為從機。
SS
:引腳 10MOSI
:引腳 11MISO
:第 12 針SCK
:引腳 13
將兩個板子共地。以下是兩塊板之間連線的圖示 -
讓我們看一下 SPI 作為 Master 和 SPI 作為 Slave 的例子。
SPI 作為 MASTER
例
#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);
}
SPI 作為 SLAVE
例
#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
}
}