当前位置: 首页 > 文档资料 > Arduino 中文教程 >

Arduino - 串行外设接口( Serial Peripheral Interface)

优质
小牛编辑
126浏览
2023-12-01

串行外设接口(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的电路板)。

  • 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中有四种操作模式如下 -

  • Mode 0 (the default) - 时钟通常为低电平(CPOL = 0),数据在从低电平到高电平(前沿)(CPHA = 0)的转换时采样。

  • Mode 1 - 时钟通常为低电平(CPOL = 0),数据在从高电平到低电平(后沿)(CPHA = 1)的转换中采样。

  • Mode 2 - 时钟通常为高电平(CPOL = 1),数据在从高电平到低电平(前沿)(CPHA = 0)的转换中进行采样。

  • Mode 3 - 时钟通常为高(CPOL = 1),数据在从低到高(后沿)(CPHA = 1)的转换中采样。

  • SPI.attachInterrupt(handler) - 从设备从主设备接收数据时要调用的函数。

现在,我们将两个Arduino UNO板连接在一起; 一个作为主人,另一个作为奴隶。

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

地面很常见。 以下是两块板之间连接的图示 -

连接板

让我们看一下SPI作为Master和SPI作为Slave的例子。

SPI作为MASTER

例子 (Example)

#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

例子 (Example)

#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
   }
}