Arduino和esp32的SPI通信:温湿度数据的发送与接收
Arduino和esp32的SPI通信:温湿度数据的发送与接收

Arduino和esp32的SPI通信:温湿度数据的发送与接收

通过SPI协议,实现Arduino和esp32的稳定和快速通信。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/weixin_43034503/article/details/135325219

 

一、项目描述

Arduino Uno R3没有联网的功能,借助esp32,可以将Arduino获取的信息传输到网络上。

Arduino和esp32能够通过RX/TX、I2C和SPI进行通信。其中,RX/TX用于连接计算机以烧录程序,I2C通常作为传感器接口,SPI很少被使用,因此,本项目使用的是SPI。

SPI(Serial Peripheral Interface,串行外设接口)是一种同步外设接口,可以使单片机以串行方式实现双工通信。SPI的特点如下。

(1)主从架构:SPI通信基于主从架构。在这个架构中,有一个主设备(如Arduino)和一个或多个从设备。主设备控制通信流程,包括时钟信号的生成。

(2)四线连接:SPI通常使用四条线进行通信:MISO(主设备输入,从设备输出)、MOSI(主设备输出,从设备输入)、SCK(时钟线)、SS(从设备选择)。SS线用于选择通信的从设备,因为一个主设备可以连接多个从设备。

(3)全双工通信:SPI支持全双工通信,这意味着数据可以同时双向传输(发送和接收)。

(4)高速:SPI是一种高速通信协议,适用于需要快速数据传输的应用。

(5)灵活:SPI协议的实现在不同的设备间可能有所不同,包括数据位宽、时钟极性和相位配置的不同。

(6)简单:与其他通信协议(如I2C或UART)相比,SPI结构相对简单,易于实现和调试。

本项目旨在使用SPI,将Arduino获取的温度值和湿度值(温湿度传感器DHT11)传输给esp32,作为“数据上网”的前提。

二、硬件连接

如下表所示,esp32和Arduino均具有SPI,只是引脚序号不同。按照下表将相同功能的引脚连接起来,即可完成SPI通信的硬件连接。例如,esp32的MISO在GPIO19引脚,Arduino的MISO在D12引脚,只需要将这两个引脚连接起来即可,其它引脚类推。

     
  Arduino esp32
SS D10 GPIO5
MOSI D11 GPIO23
MISO D12 GPIO19
SCK D13 GPIO18

三、软件编程

Arduino和esp32基于两种不同的芯片,但都支持由Arduino IDE上传程序。因此,本项目使用Arduino IDE作为编程软件。

为了平衡Arduino和esp32的工作量,使两个硬件的程序长度不要相差太远,本项目将arduino作为SPI的从设备,将esp32作为SPI的主设备。

首先,新建一个arduino_slave.ino,负责读取温湿度传感器(DHT11)获取的温度值和湿度值,并且以字符的格式发送出去。DHT11库在通过Arduino IDE中的“库管理”进行安装。

#include <DHT11.h>
#include <SPI.h>

DHT11 dht11(2);
String dataToSend;
volatile int index = 0;

void setup() {
  // 设置串口波特率
  Serial.begin(9600);
  // 启动SPI,设置为SPI从设备
  pinMode(MISO, OUTPUT);
  // 启动SPI的中断例程ISR
  SPCR |= _BV(SPE);
  SPI.attachInterrupt();
}

ISR(SPI_STC_vect) {
  if (index < dataToSend.length()) {
    // 发送当前字符,具体的数据处理由主设备实现
    SPDR = dataToSend[index++];
  } else {
    // 发送结束字符
    SPDR = 0;
    // 重置索引
    index = 0;
  }
}

void loop() {
  // 从DHT11读取温度和湿度
  int temperature = dht11.readTemperature();
  int humidity = dht11.readHumidity();

  if (temperature != DHT11::ERROR_CHECKSUM && temperature != DHT11::ERROR_TIMEOUT && humidity != DHT11::ERROR_CHECKSUM && humidity != DHT11::ERROR_TIMEOUT) {
    // 创建带有标志位的字符串
    dataToSend = "<Temperature:" + String(temperature) + ",Humidity:" + String(humidity) + ">";
    Serial.println(dataToSend);
  } else {
    // 打印错误信息
    dataToSend = "<Error: Sensor Read Failed>";
    Serial.println(dataToSend);
  }
  // 重置索引,准备下一次发送
  index = 0;
  // 延时
  delay(1000);
}

![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

然后,新建一个esp32_master.ino,接收来自Arduino发送过来的字符。

#include <SPI.h>

const int ssPin = 5;
String receivedData;

void setup() {
  // 设置串口波特率
  Serial.begin(9600);
  // 启动SPI,设置为SPI主设备
  SPI.begin();
  pinMode(ssPin, OUTPUT);
}

void loop() {
  // 开始通信
  digitalWrite(ssPin, LOW);
  // 准备接收数据
  receivedData = "";
  bool isMessageStarted = false;
  char receivedChar = 0;
  //
  while (true) {
    // 接收字符
    receivedChar = (char)SPI.transfer(0x00);
    // 整合数据,不包括标志位<>
    if (receivedChar == '<') {
      isMessageStarted = true;
    } else if (receivedChar == '>' && isMessageStarted) {
      break;
    } else if (isMessageStarted) {
      receivedData += receivedChar;
    }
  }
  // 结束通信
  digitalWrite(ssPin, HIGH);
  // 打印接收到的数据
  Serial.println(receivedData);
  // 延时
  delay(1000);
}

![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

在上述两个程序中,发送的数据内容和接收的数据内容一致,“<”是开始标志,“>”是结束标志。之所以采用开始标志和结束标志,是为了保障收发数据的完整性和统一性。

发送的数据内容是:<Temperature:temperature,Humidity:humidity>

接收的数据内容是:<Temperature:temperature,Humidity:humidity>

当运行程序时,可以观察到esp32的串口监视器打印出如下信息。这是因为esp32接收到数据后,丢弃开始标志“<”和结束标志“>”,只保留真正需要的信息。

`Temperature:temperature,Humidity:humidity`

由此,Arduino通过DHT11获取了当前环境的温度值和湿度值,并通过SPI传送给esp32,使Arduino获取的数据可以借助esp32上传到网络。

pdf_watermark

内容来源:csdn.net

作者昵称:ice小游

原文链接:https://blog.csdn.net/weixin_43034503/article/details/135325219

作者主页:https://blog.csdn.net/weixin_43034503

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注