Arduino 串行外设接口

串行外设接口(SPI)总线是用于串行通信的系统,最多可使用四个导体,通常为三个。一个导体用于数据接收,一个导体用于数据发送,一个导体用于同步,另一个导体用于选择与之通信的设备。它是一个全双工连接,这意味着数据是同时发送和接收的。最大波特率高于I2C通信系统中的波特率。

板的SPI引脚

SPI使用以下四条线:

  • SCK – 这是由主机驱动的串行时钟。
  • MOSI – 这是由主机驱动的主输出/从输入。
  • MISO – 这是由主机驱动的主输入/从输出。
  • SS – 这是从机选择线。

使用以下函数,必须包括SPI.h.

  • SPI.begin() – 通过将SCK,MOSI和SS设置为输出来初始化SPI总线,将SCK和MOSI拉低,将SS拉高。
  • SPI.setClockDivider(分频器) – 相对于系统时钟设置SPI时钟分频器。在基于AVR的板上,可用的分频器为2,4,8,16,32,64或128。默认设置为SPI_CLOCK_DIV4,它将SPI时钟设置为系统时钟的四分之一(对于20 MHz的电路板为5 Mhz)。
  • 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板连接在一起;一个作为主机,另一个作为从机。

  • (SS):引脚10
  • (MOSI):引脚11
  • (MISO):引脚12
  • (SCK):引脚13

接地是常见的。以下是两个电路板之间的连接的图示:

Arduino 串行外设接口

让我们看看SPI作为主机和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);


  }

SPI为从机

例子

#include &lt;SPI.h&gt;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 &lt;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
     
   }
  }