📅  最后修改于: 2020-11-05 03:38:23             🧑  作者: Mango
串行外围设备接口(SPI)总线是用于串行通信的系统,它最多使用四根导线,通常为三根。一根导线用于数据接收,一根导线用于数据发送,一根导线用于同步,另一根导线用于选择要与之通信的设备。这是全双工连接,这意味着将同时发送和接收数据。最大波特率高于I2C通信系统中的波特率。
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传输基于同时发送和接收:接收到的数据以receiveVal返回。
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
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
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
}
}