串行外围设备接口(SPI)总线是用于串行通信的系统,它最多使用四根导线,通常为三根,一根导线用于数据接收,一根导线用于数据发送,一根导线用于同步,另一根导线用于选择要与之通信的设备,这是全双工连接,这意味着将同时发送和接收数据,最大波特率高于I2C通信系统中的波特率。
Board SPI Pins
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时钟设置为系统时钟频率的四分之一(对于5Mhz,板以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传输基于同时发送和接收:接收到的数据在receiveVal中返回。
SPI.beginTransaction(SPISettings(speedMaximum,dataOrder,dataMode)) - speedMaximum是时钟,dataOrder(MSBFIRST或LSBFIRST),dataMode(SPI_MODE0,SPI_MODE1,SPI_MODE2或SPI_MODE3)
我们在SPI中有以下四种操作模式-
Mode 0(默认) - 时钟通常为低电平(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作为主设备和SPI作为从设备的示例。
SPI as MASTER
#include <SPI.h> void setup (void) { Serial.begin(115200); //将 usart 的波特率设置为 115200 digitalWrite(SS, HIGH); //禁用从选择 SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8);//将时钟除以 8 } void loop (void) { char c; digitalWrite(SS, LOW); //启用从机选择 //发送测试字符串 for (const char * p="Hello, Learnfk!\r" ; c=*p; p++) { SPI.transfer (c); Serial.print(c); } digitalWrite(SS, HIGH); //禁用从选择 delay(2000); }
SPI as SLAVE
#include <SPI.h> char buff [50]; volatile byte indx; volatile boolean process; void setup (void) { Serial.begin (115200); pinMode(MISO, OUTPUT); //必须发送到主控,所以它设置为输出 SPCR |= _BV(SPE); //在从模式下打开 SPI indx=0; //缓冲区空 process=false; SPI.attachInterrupt(); //开启中断 } ISR (SPI_STC_vect) //SPI中断程序 byte c=SPDR; //从 SPI 数据寄存器读取字节 if (indx < sizeof buff) { buff [indx++]=c; //将数据保存在数组缓冲区的下一个索引中 if (c == '\r') //检查单词的结尾 process=true; } } void loop (void) { if (process) { process=false; //重置进程 Serial.println (buff); //在串行监视器上打印阵列 indx= 0; //将按钮重置为零 } }
参考链接
https://www.learnfk.com/arduino/arduino-serial-peripheral-interface.html
标签:process,CLOCK,SS,void,Arduino,无涯,SPI,串口,时钟 From: https://blog.51cto.com/u_14033984/7941942