如何在Arduino IDE中通过ESP8266读取STM32的UART数据包?
ESP8266读取STM32串口数据的实现方案
基础字符串格式读取与拆分
你的STM32通过UART发送的是空格分隔的11个整数+1个浮点数,以分号结尾的字符串数据包。ESP8266端可以按以下步骤读取解析:
实现代码
void setup() { // 初始化串口,波特率必须和STM32的UART配置一致 Serial.begin(115200); // 若使用非默认串口引脚,可改用SoftwareSerial: // #include <SoftwareSerial.h> // SoftwareSerial stm32Serial(D2, D3); // RX接STM32的TX,TX接STM32的RX // stm32Serial.begin(115200); } void loop() { // 检查串口是否有数据 if (Serial.available() > 0) { // 读取到分号为止,获取完整数据包 String receivedPacket = Serial.readStringUntil(';'); if (receivedPacket.length() > 0) { // 定义对应变量存储解析结果 int32_t ir_average, red_average, dcFilterIRresult, dcFilterRedresult; int32_t chebyshevResult2, elipticResult2, wyjscie, bpm_up; int32_t fftbmp, currentSaO2Value, spo2Calib; float temp; // 用sscanf按格式解析,格式需和STM32的sprintf完全匹配 int parseCount = sscanf(receivedPacket.c_str(), "%d %d %d %d %d %d %d %d %d %d %d %f", &ir_average, &red_average, &dcFilterIRresult, &dcFilterRedresult, &chebyshevResult2, &elipticResult2, &wyjscie, &bpm_up, &fftbmp, ¤tSaO2Value, &spo2Calib, &temp); if (parseCount == 12) { // 成功解析全部12个数据 // 这里处理解析后的数据,示例:打印 Serial.print("IR平均: "); Serial.println(ir_average); Serial.print("实时血氧: "); Serial.println(currentSaO2Value); Serial.print("温度: "); Serial.println(temp); // 其他数据按需处理 } else { // 解析失败,输出错误信息 Serial.print("解析失败,原始数据包: "); Serial.println(receivedPacket); } } } }
更优实现方案:二进制数据包传输
字符串格式虽然直观,但解析效率低且容易因字符传输错误导致解析失败。更可靠高效的方式是直接传输二进制数据,步骤如下:
1. STM32端修改发送逻辑
定义统一的结构体存储传感器数据,直接发送结构体的字节流:
// 定义数据结构体,确保字段顺序和类型与ESP8266端一致 typedef struct { int32_t ir_average; int32_t red_average; int32_t dcFilterIRresult; int32_t dcFilterRedresult; int32_t chebyshevResult2; int32_t elipticResult2; int32_t wyjscie; int32_t bpm_up; int32_t fftbmp; int32_t currentSaO2Value; int32_t spo2Calib; float temp; } SensorData; // 填充数据并发送 SensorData sensorData = { ir_average, red_average, dcFilterIRresult, dcFilterRedresult, chebyshevResult2, elipticResult2, wyjscie, bpm_up, fftbmp, currentSaO2Value, spo2Calib, temp }; HAL_UART_Transmit(&huart4, (uint8_t*)&sensorData, sizeof(SensorData), 1000);
2. ESP8266端读取解析
同样定义相同的结构体,直接读取对应字节数并解析:
// 与STM32端完全一致的结构体定义 typedef struct { int32_t ir_average; int32_t red_average; int32_t dcFilterIRresult; int32_t dcFilterRedresult; int32_t chebyshevResult2; int32_t elipticResult2; int32_t wyjscie; int32_t bpm_up; int32_t fftbmp; int32_t currentSaO2Value; int32_t spo2Calib; float temp; } SensorData; void setup() { Serial.begin(115200); } void loop() { // 检查是否接收到完整的数据包(结构体大小) if (Serial.available() >= sizeof(SensorData)) { SensorData receivedData; // 读取全部字节到结构体 Serial.readBytes((uint8_t*)&receivedData, sizeof(SensorData)); // 直接使用结构体中的数据 Serial.print("FFT心率: "); Serial.println(receivedData.fftbmp); Serial.print("校准血氧: "); Serial.println(receivedData.spo2Calib); Serial.print("温度: "); Serial.println(receivedData.temp); } }
额外优化:添加数据校验
为避免传输过程中的数据损坏,可在结构体末尾添加校验字段(如CRC或校验和):
- STM32端:计算所有字段的和或CRC值,添加到结构体最后一起发送
- ESP8266端:接收后重新计算校验值,与收到的校验值对比,一致再使用数据
内容的提问来源于stack exchange,提问作者Jakub Beling
相关产品推荐
相关产品推荐

