ESP32双机串口通信实现详解

ESP32串口

ESP32双机串口通信

环顾论坛居然无使用uart进行双击通信的案例或者讲解!!!
还是自己摸索吧!环境依旧是arduino(熟练使用ESP32后必得用vs code,这个IDE居然有时候函数不能跳转!!!)

双向通信代码

先贴代码(使用串口2,GPIO16、17):
esp32发送端

void setup() {
  // 启动串口调试输出
  Serial.begin(115200);
  // 初始化 ESP32 的串口2
  Serial2.begin(921600);
}


void loop() {
  // 发送一串数据到 ESP32 的串口2
  byte sendData[] = {0xF1, 0xF2, 0xF3, 0xF4, 0xFF, 0xF1};
  Serial2.write(sendData, sizeof(sendData));
  // 输出发送的数据
  Serial.print("Sent data: ");
  for (int i = 0; i < sizeof(sendData); i++) {
    Serial.print(sendData[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  delay(1000);
}

esp32接收端

// 中断处理函数
void serial2ISR() {
  // 检查是否有可用数据从 ESP32 的串口2 接收
  if (Serial2.available()) {
    byte receivedData[6];
    // 读取 6 个字节到 receivedData 数组中
    Serial2.readBytes(receivedData, 6);
   
    // 输出接收到的数据
    Serial.print("Received data: ");
    for (int i = 0; i < 6; i++) {
      Serial.print(receivedData[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

void setup() {
  // 启动串口调试输出
  Serial.begin(115200);
  // 初始化 ESP32 的串口2
  Serial2.begin(921600);
  // 配置串口2的RX引脚为中断模式
  pinMode(16, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(16), serial2ISR, FALLING);
}

void loop() {
  // do nothing
}


注意:接收端不采用循环,目的当然是为了进行其他程序,必须cpu循环判断串口缓冲区的状态!
真心不推荐下列写法: 阻塞式代码是指会导致程序停止运行,直到某个操作完成的代码。

while (!Serial.available()) { 
// 等待串口有可用数据 
}

串口常用函数介绍

好了,进入串口函数使用

1. 初始化串口

首先设置波特率以及数据位、检验位和停止位,然后设置收发引脚以及参数是否反转信号和超时时间。

// 启动串口调试输出
  Serial.begin(115200);
  // 初始化 ESP32 的串口2
  Serial2.begin(921600);
//void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms)


//baud参数是波特率,config参数是数据位、校验位和停止位的设置,rxPin和txPin参数是接收和发送数据的引脚,invert参数是是否反转信号,timeout_ms参数是超时时间。
// Serial2.begin(115200, SERIAL_8N1, 16, 17);

2. 串口打印

Serial.print(" ");
Serial.println();

区别在于print打印不换行,println打印换行
共同点:打印数值(可打印进制数)、字符、字符串

3. 串口输出数据

Serial2.write(sendData, sizeof(sendData));
//原型:write(const uint8_t *buffer, size_t size)

可以使用该串口输出数据,第一个参数是数据指针,size当然就是数据大小
还有一种简单方法输出数据

Serial.print();
Serial.println();

4. 串口缓冲区状态

Serial.available()

判断串口缓冲区的状态, 可以检查是否有数据可用

5. 读取串口字节

Serial.read();

读取串口一个字节, 如果已经接收到数据,则返回值为接收到的字节;否则返回 -1。

6. 读取串口字符串数据

Serial.readString();

读取字符串数据。该函数没有参数。如果已经接收到数据,则返回一个 String 对象,其中包含接收到的字符串;否则返回空字符串。

7. 读取多个字节数据

Serial.readBytes(buffer, length)
Serial.readBytesUntil(terminator, buffer, length);

读取多个字节的数据。buffer 参数是一个字节数组,用于存储读取到的数据;length 参数指定要读取的字节数。readBytes() 函数会一直阻塞程序,直到读取到指定长度的数据;而 readBytesUntil() 函数会在读取到终止字符(如\n)或达到最大长度时停止读取数据。这两个函数返回值为实际读取的字节数。

Serial.setTimeout(timeout)

设置在调用 readBytesUntil() 函数时等待数据到达的最长时间(以毫秒为单位)。timeout 参数是一个整数,表示最长等待时间。该函数没有返回值。

字符串简单示例:
发送端:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(921600);
  Serial.println("init success!");
}

void loop() {
  // put your main code here, to run repeatedly:
  char *payload_char = "0xE0,0x5A,0x1B,0x6C,0x45,0x78";
  Serial.println(payload_char);
  Serial2.println(payload_char);
  delay(2000);
}

接收端:

void task1_uart2(void *pvParameters) {
  // Task 1 code here

  for (;;) {

    if (Serial2.available()) {
      String receivedData = Serial2.readString();
      Serial.print("receivedData: ");
      Serial.println(receivedData);
    }
    vTaskDelay(5);
  }
  //正常不会执行到这里
  vTaskDelete(NULL);
}
物联沃分享整理
物联沃-IOTWORD物联网 » ESP32双机串口通信实现详解

发表评论