文章编写背景
前一阵子项目中需要将K210的图像数据传输到app中,于是需要一个通信模块作辅助,选择ESP32-Wroom-32D作为通信模块。图像传输协议自然为SPI通信,快速而简单,于是K210通过MicroPython作为主通信设备,Esp32通过Arduino编写从设备代码,完成主从设备的SPI数据传输。
但是!!!!!问题来了,除了ESP32的DMA缓冲区问题等等,我发现从设备根本不通(直接调用Arduino的SPI库)!
咱就去网上找相关资料,发现调用这个官方SPI库的例程
#include <SPI.h>
都是作为主设备使用,唯一的SPI从设备(ESP32开发板)还是ESP-IDF的例程,这怎么可能!!!
我是真的不相信ESP32在Arduino这个热门环境中没有SPI的简单例子,但是!百方查找,还就是没有。直到科学上网遇到了一个github库,专门为SPI从设备建立了一个库文件,参考下方链接:
https://github.com/hideakitai/ESP32SPISlave
这个老哥(赞赞赞)编写了SPI从模式库文件和使用DMA的从模式库,良心呀!!还贴心提示了DMA使用情况下的数据缺失问题(每一包缺失4字节),通过该库文件编写从模式代码,终于跟K210的master开发板建立了链接,并且成功完成图像传输。
mark
终于完成了既定的任务,后面开始填坑机智云app讲解内容。
SPI通信简介
SPI(Serial Peripheral Interface)是一种高速、全双工、同步的通信协议,常用于微控制器与外围设备之间的数据传输。SPI通信通常涉及一个主设备和一个或多个从设备,通过四根信号线进行通信:SCLK(时钟线)、MOSI(主设备输出从设备输入)、MISO(主设备输入从设备输出)和SS(从设备选择线)。
MicroPython中的SPI通信
在MicroPython中,SPI通信可以通过machine
模块中的SPI
类来实现。以下是一个简单的SPI通信示例:
from machine import Pin, SPI
# 初始化SPI
spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
# 选择从设备
cs = Pin(15, Pin.OUT)
cs.value(0)
# 发送数据
spi.write(b'Hello')
# 接收数据
data = spi.read(5)
# 取消选择从设备
cs.value(1)
Arduino环境下ESP32的SPI通信
在Arduino环境下,ESP32的SPI通信可以通过SPI
库来实现。以下是一个简单的SPI通信示例:
#include <ESP32SPISlave.h>
ESP32SPISlave slave;
static constexpr size_t BUFFER_SIZE = 8;
static constexpr size_t QUEUE_SIZE = 1;
uint8_t tx_buf[BUFFER_SIZE] {1, 2, 3, 4, 5, 6, 7, 8};
uint8_t rx_buf[BUFFER_SIZE] {0, 0, 0, 0, 0, 0, 0, 0};
void setup()
{
// 初始化串口通信
Serial.begin(115200);
Serial.println("HSPI Slave Mode Test");
slave.setDataMode(SPI_MODE0); // default: SPI_MODE0
slave.setQueueSize(QUEUE_SIZE); // default: 1
// begin() after setting
slave.begin(); // default: HSPI (please refer README for pin assignments)
}
void loop()
{
// do some initialization for tx_buf and rx_buf
// start and wait to complete one BIG transaction (same data will be received from slave)
const size_t received_bytes = slave.transfer(tx_buf, rx_buf, BUFFER_SIZE);
// do something with received_bytes and rx_buf if needed
// 通过串口打印接收到的数据
// 输出 rx_buf 中的所有数据
Serial.print("Received data: ");
for (size_t i = 0; i < BUFFER_SIZE; ++i) {
Serial.print(rx_buf[i]); // 输出
Serial.print(" ");
}
Serial.println(); // 输出完一行后换行
delay(1);
}
MicroPython与Arduino环境下ESP32的SPI通信对比
MicroPython和Arduino环境下的SPI通信在实现方式上有所不同。MicroPython使用machine
模块中的SPI
与类,而Arduino使用<ESP32SPISlave.h>
库。两者都需要初始化SPI并设置从设备选择引脚,但在数据传输的具体实现上有所差异。MicroPython使用write
和read
方法进行数据传输,而Arduino使用transfer
方法。
注意事项
在使用SPI通信时,需要注意以下几点:
- 确保主设备和从设备的时钟极性(polarity)和相位(phase)设置一致。
- 从设备选择引脚(SS)在通信过程中需要正确控制,以避免多个从设备同时响应。
- 数据传输速率(baudrate)应根据设备的要求进行设置,以确保通信的稳定性。
通过以上方法,可以在MicroPython和Arduino环境下实现ESP32的SPI通信。