简介
串行外设接口(SPI)是一种同步串行通信协议,广泛用于将微控制器连接到传感器、显示屏和存储芯片。在本教程中,我们将使用 Velxio 模拟器构建一个 SPI 回环测试。回环测试通过 SPI 发送字节并读取响应,以确认协议正常工作。由于没有物理从设备,模拟器会返回发送的字节,这使得它成为无需任何硬件即可学习 SPI 的理想方式。
电路讲解
让我们从搭建电路开始。我们需要的唯一组件是一块 Arduino Uno,将其放置在画布上。

要添加 Arduino Uno,请点击画布工具栏上的“+”图标,打开组件选择器。

搜索“Arduino Uno”并将其放置在画布上。Arduino Uno 有专用的 SPI 引脚:
- MOSI(主出从入)– 引脚 11
- MISO(主入从出)– 引脚 12
- SCK(串行时钟)– 引脚 13
- SS(从选择)– 引脚 10(我们将用作片选)
在此回环测试中,我们不需要任何外部接线,因为 SPI 信号在 Arduino 内部。但是,我们必须确保 SS 引脚(引脚 10)配置为输出,并在初始时拉高,在通信期间拉低。代码会处理这些。
代码讲解
现在让我们检查代码。点击编辑器工具栏中的“代码”选项卡,打开代码编辑器。

代码使用 Arduino C++ 编写,并使用了内置的 SPI.h 库。无需外部库。
// SPI Loopback Test
// Sends bytes via SPI and logs the exchange.
// Without a physical slave, the emulator returns the sent byte.
#include <SPI.h>
#define SS_PIN 10
void setup() {
Serial.begin(9600);
Serial.println("========================");
Serial.println(" SPI Protocol Test");
Serial.println("========================");
Serial.println();
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV16);
Serial.println("SPI initialized.");
Serial.print("Clock divider: 16 (");
Serial.print(F_CPU / 16);
Serial.println(" Hz)");
Serial.println();
// Send test pattern
Serial.println("Sending test pattern via SPI:");
byte testData[] = {0xAA, 0x55, 0xFF, 0x00, 0x42, 0xDE, 0xAD, 0xBE};
digitalWrite(SS_PIN, LOW); // Select slave
for (int i = 0; i < sizeof(testData); i++) {
byte sent = testData[i];
byte received = SPI.transfer(sent);
Serial.print(" TX: 0x");
if (sent < 16) Serial.print("0");
Serial.print(sent, HEX);
Serial.print(" RX: 0x");
if (received < 16) Serial.print("0");
Serial.print(received, HEX);
if (sent == received) {
Serial.println(" (loopback OK)");
} else {
Serial.println();
}
}
digitalWrite(SS_PIN, HIGH); // Deselect slave
Serial.println();
Serial.println("SPI test complete.");
}
void loop() {
delay(1000);
}
让我们分解关键部分:
#include <SPI.h>:包含 Arduino SPI 库。#define SS_PIN 10:将从选择引脚定义为引脚 10。setup():以 9600 波特率初始化串行通信,将 SS 引脚设置为输出并拉高,然后调用SPI.begin()初始化 SPI 外设。时钟分频器设置为 16,时钟频率为F_CPU / 16(对于 16 MHz 的 Arduino 为 1 MHz)。- 测试模式:一个包含 8 个字节的数组(
0xAA, 0x55, 0xFF, 0x00, 0x42, 0xDE, 0xAD, 0xBE)被逐个发送。 digitalWrite(SS_PIN, LOW):选择从设备(在回环中,这只是一个逻辑步骤)。SPI.transfer(sent):发送一个字节并同时接收一个字节。在回环中,接收到的字节等于发送的字节。- 串行输出:每次传输都以十六进制格式打印,如果发送和接收的字节匹配,则附加“(loopback OK)”。
digitalWrite(SS_PIN, HIGH):传输完成后取消选择从设备。loop():除了一个延迟外为空,因为测试仅在setup()中运行一次。
关键概念
- SPI 协议:SPI 是一种同步、全双工协议,有四条线:MOSI、MISO、SCK 和 SS。主设备生成时钟并控制从设备选择。
- 回环:将 MOSI 连接到 MISO(或使用回显的模拟器)允许在没有外部从设备的情况下测试 SPI 硬件。
- 时钟分频器:
SPI.setClockDivider()函数设置相对于系统时钟的 SCK 频率。较低的分频器意味着更快的通信。 SPI.transfer():此函数同时发送和接收一个字节。它是 SPI 通信的核心。
常见陷阱与调试技巧
- SS 引脚配置:SS 引脚必须配置为输出;否则,SPI 硬件可能会自动切换到从模式。始终设置
pinMode(SS_PIN, OUTPUT)并在空闲时将其拉高。 - 波特率不匹配:确保串行监视器波特率与
Serial.begin(9600)匹配。在 Velxio 中,串行监视器会自动打开。 - 时钟极性和相位:默认 SPI 模式(模式 0)使用 SCK 空闲低电平并在上升沿采样数据。如果您的从设备需要不同的模式,请使用
SPI.setDataMode()。 - 无外部接线:在此回环测试中,不需要接线。如果您要连接实际的从设备,请仔细检查连接:MOSI 到 MOSI,MISO 到 MISO,SCK 到 SCK,SS 到 SS。
建议的扩展
- 添加外部从设备:通过添加第二个 Arduino 作为从设备并编写从设备草图,模拟传感器或显示屏。
- 更改时钟速度:尝试不同的时钟分频器(例如
SPI_CLOCK_DIV2、SPI_CLOCK_DIV128),并观察对传输速度的影响。 - 发送更多数据:修改测试模式以发送字符串或传感器读数。
- 使用中断:实现带中断的 SPI 通信,以实现非阻塞传输。
亲自尝试
准备好开始了吗?在 Velxio 中打开实时示例并运行模拟。您将看到串行输出显示每个发送和接收的字节,确认回环成功。
祝模拟愉快!