环顾论坛居然无使用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);
}