|
微控制器使用许多不同的协议与各种传感器和外围设备进行通信。有许多用于无线和有线通信的协议,并且最常用的通信技术是串行通信。串行通信是通过通信信道或总线一次一位地发送数据的过程。有许多类型的串行通信,如UART、CAN、USB、I2C和SPI通信。
在本篇文章中,我们将了解SPI协议以及如何在Arduino中使用它。我们将使用SPI协议在两个Arduino开发板之间进行通信。在这里,一个Arduino开发板将充当主机Master,另一个将充当从机Slave,分别有两个LED和按钮连接到两个arduino开发板。为了演示SPI通信,我们将使用SPI串行通信协议通过从站侧的按钮控制主机的LED,反之亦然。
什么是SPI? SPI(串行外设接口)是一种串行通信协议。摩托罗拉在1970年发明了SPI接口。SPI具有全双工连接,这意味着数据可以同时发送和接收。即主设备可以将数据发送到从设备,从设备可以同时向主设备发送数据。 SPI是同步串行通信意味着通信需要时钟。
SPI的工作过程 SPI使用四条线进行主/从通信。 SPI只能有一个主站,并且可以有多个从站。主设备通常是微控制器,从设备可以是微控制器、传感器、ADC、DAC、LCD等。
下面是SPI主机带单个从机的框图表示。
SPI有四条线MISO、MOSI、SS和CLK ● MISO(主进从出) - 用于向主设备发送数据的从设备线。 ● MOSI(主出从入) - 用于向外设发送数据的主线。 ● SCK(串行时钟) - 同步主机产生的数据传输的时钟脉冲。 ● SS(从机选择)-Master可以使用此引脚来启用和禁用特定设备。
SPI主站带多个从站的框图
要启动主机和从机之间的通信,我们需要将所需设备的从机选择(SS)引脚设置为低电平,以便它可以与主机通信。当该引脚为高电平时,它会忽略主机。这允许您让多个SPI设备共享相同的MISO、MOSI和CLK主线。如上图所示,有四个从器件,其中SCLK、MISO,MOSI与主器件共用,每个器件的SS分别连接到主器件的各个SS引脚(SS1、SS2、SS3)。通过将所需的SS引脚设置为低电平,主器件可以与该从器件通信。
Arduino UNO中的SPI引脚 下图显示了Arduino UNO中的SPI引脚(红色框中)。
SPI线 | Arduino引脚 | MOSI | 11或ICSP-4 | MISO | 12或ICSP-1 | SCK | 13或ICSP-3 | SS | 10 |
在Arduino中使用SPI 在开始编程两个Arduinos之间的SPI通信之前。我们需要了解Arduino IDE中使用的SPI库。
库<SPI.h>包含在程序中,用于使用以下SPI通信函数。 1. SPI.begin() 用途:通过将SCK、MOSI和SS设置为输出来初始化SPI总线,将SCK和MOSI拉低,SS为高电平。
2. SPI.setClockDivider(divider) 用途:设置相对于系统时钟的SPI时钟分频器。可用的分频器为2,4,8,16,32,64或128。 divider参数: ◾ SPI_CLOCK_DIV2 ◾ SPI_CLOCK_DIV4 ◾ SPI_CLOCK_DIV8 ◾ SPI_CLOCK_DIV16 ◾ SPI_CLOCK_DIV32 ◾ SPI_CLOCK_DIV64 ◾ SPI_CLOCK_DIV128
3. SPI.attachInterrupt(handler) 用途:当从设备从主设备接收数据时,将调用此函数。
4. SPI.transfer(val) 用途:此函数用于在主站和从站之间同时发送和接收数据。
现在让我们从Arduino中SPI协议的实际演示开始。在本篇文章中,我们将使用两个arduino中的一个作为master,另一个作为slave。两个Arduino都分别带有一个LED和一个按钮。主LED可以通过使用从机Arduino的按钮来控制,从机Arduino的LED可以通过主Arduino的按钮使用arduino中的SPI通信协议来控制。
需要的组件 ● Arduino UNO开发板 ● LED指示灯 ● 按钮 ● 电阻10k ● 电阻2.2k ● 面包板 ● 连接导线
Arduino SPI通信电路图
编程说明 本教程有两个程序,一个用于主arduino,另一个用于从机arduino。在本文的末尾处,提供了两个Arduino开发板的完整程序。
主机Arduino编程介绍 1.首先,我们需要包含SPI库以使用SPI通信函数。
2.在void setup()函数中,我们以波特率115200启动串行通信。 将LED连接至引脚7,将按钮连接至引脚2,并分别设置这些引脚OUTPUT和INPUT。 - pinMode(ipbutton,INPUT);
- pinMode(LED,OUTPUT);
复制代码接下来我们开始SPI通信 接下来,我们设置Clockdivider进行SPI通信。这里我们设置了分频系数8。 - SPI.setClockDivider(SPI_CLOCK_DIV8);
复制代码然后将SS引脚置为高电平,因为我们没有启动任何传输到从机arduino。
3.在void loop()函数中: 我们读取了连接到pin2(Master Arduino)的按钮引脚的状态,用于将这些值发送到从Arduino。
- buttonvalue = digitalRead(ipbutton);
复制代码根据引脚2的输入设置逻辑以设置x值(发送到从机) - if(buttonvalue == HIGH)
- {
- x = 1;
- }
- else
- {
- x = 0;
- }
复制代码
在发送值之前,我们需要将从机选择值设置为LOW以开始从主设备传输到从设备。
以下是重要的一步,在下面的语句中,我们将存储在Mastersend变量中的按钮值发送到从机arduino,并从slave中接收将存储在Mastereceive变量中的值。 - Mastereceive=SPI.transfer(Mastersend);
复制代码之后,根据Mastereceive值,我们将点亮或熄灭主机Arduino上的LED灯。 - if(Mastereceive == 1)
- {
- digitalWrite(LED,HIGH); //Sets pin 7 HIGH
- Serial.println("Master LED ON");
- }
- else
- {
- digitalWrite(LED,LOW); //Sets pin 7 LOW
- Serial.println("Master LED OFF");
- }
复制代码注意:我们使用serial.println()在Arduino IDE的串行监视器中查看结果。
从机Arduino编程代码介绍 1.首先,我们需要包含SPI库以使用SPI通信函数。
2.在void setup()函数中,我们以波特率115200启动串行通信。 将LED连接至引脚7,将按钮连接至引脚2,并分别设置这些引脚OUTPUT和INPUT。 - pinMode(ipbutton,INPUT);
- pinMode(LED,OUTPUT);
复制代码这里重要的一步是 以上语句将MISO设置为OUTPUT(必须将数据发送到主IN)。所以数据是通过Slave Arduino的MISO发送的。
现在使用SPI控制寄存器在从模式下打开SPI
然后打开SPI中断的中断。如果从主站接收数据,则调用中断例程,并从SPDR(SPI数据寄存器)获取接收值 来自master的值取自SPDR并存储在Slavereceived变量中。这发生在以下中断例程函数中。 - ISR (SPI_STC_vect)
- {
- Slavereceived = SPDR;
- received = true;
- }
复制代码
3.接下来在void loop()函数中,我们根据Slavereceived值将从机arduino上的LED灯设置为ON或OFF。 - if (Slavereceived==1)
- {
- digitalWrite(LEDpin,HIGH); //Sets pin 7 as HIGH LED ON
- Serial.println("Slave LED ON");
- }
- else
- {
- digitalWrite(LEDpin,LOW); //Sets pin 7 as LOW LED OFF
- Serial.println("Slave LED OFF");
- }
复制代码
接下来,我们读取从机Arduino按钮的状态,并将值存储在Slavesend中,通过给SPDR寄存器赋值将值发送给主机Arduino。
- buttonvalue = digitalRead(buttonpin);
- if (buttonvalue == HIGH)
- {
- x=1;
- }
- else
- {
- x=0;
- }
- Slavesend=x;
- SPDR = Slavesend;
复制代码
注意:我们使用serial.println()在Arduino IDE的串行监视器中查看结果。
测试硬件 下面是两个Arduino开发板之间SPI通信的最终设置图。
按下主侧的按钮时,从机侧的白色LED变为ON。
当按下从属侧的按钮时,主侧的红色LED亮。
代码 以下是主机侧和从机侧Arduino开发板的完整代码:
main.rar
(1.28 KB, 下载次数: 151)
|