串行外设接口 (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
接地是常见的. 以下是两个电路板之间的连接的图示:
让我们看看 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 <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
- }
- }
来源: http://www.bubuko.com/infodetail-3141902.html