Arduino I2C通信异常:无法完整接收数据且启动时出现乱码
Arduino I2C通信问题排查与修复
问题现象
- 主控Arduino无法接收第4路传感器数据,但从控端串口能正常输出该路数据
- 设备启动时偶尔出现串口乱码,后续自动消失
问题根源分析
- I2C响应逻辑错误:从控端错误地将主
loop()函数绑定到Wire.onRequest()回调。I2C请求响应要求回调函数必须快速执行、无延迟,但主loop()里有delay(1000),且零散发送单路数据,会导致I2C通信超时,最终丢失最后一路数据。 - 数据发送时机错误:从控在主循环中逐路调用
Wire.write(),但I2C的requestFrom是一次性请求数据,这种零散发送方式会导致主控端无法完整接收所有数据。 - 启动乱码:Arduino启动时串口硬件未完全初始化,此时输出数据会出现乱码。
修复方案
- 为从控端创建独立的I2C请求响应函数,在该函数中一次性组装所有4路传感器数据并发送
- 将
Wire.onRequest()绑定到新的响应函数,而非主loop() - 主
loop()仅负责更新传感器数据,不处理I2C发送逻辑 - 增加串口初始化延迟,解决启动乱码问题
修改后代码
主控代码
#include <Wire.h> void setup() { Serial.begin(9600); Wire.begin(); // 延迟确保串口稳定初始化 delay(500); } void loop() { char buffer[128]; // 扩大缓冲区,容纳4路完整数据 int bytesReceived = Wire.requestFrom(1, sizeof(buffer)-1); // 预留1位给字符串结束符 if (bytesReceived > 0) { int index = 0; while (Wire.available() && index < sizeof(buffer)-1) { buffer[index++] = Wire.read(); } buffer[index] = '\0'; // 添加结束符避免乱码 Serial.print(buffer); } delay(1000); // 与从控同步采样间隔 }
从控代码
#include <Wire.h> // 存储4路传感器数据,供I2C响应函数调用 String sensorData[4]; void setup() { Wire.begin(1); // 绑定专用的I2C请求响应函数 Wire.onRequest(sendSensorData); Serial.begin(9600); delay(500); // 延迟确保串口初始化完成 } void loop() { // 主循环仅更新传感器数据,不处理I2C发送 for (int i = 0; i < 4; i++) { int reading = analogRead(A0 + i); float voltage = reading * (5000.0 / 1024.0); // 用浮点型5000.0避免整数截断丢失精度 float temp = voltage / 10; sensorData[i] = "S_" + String(i + 1) + ", " + String(temp) + "\n"; Serial.print(sensorData[i]); } delay(1000); } // I2C请求响应函数:快速发送所有传感器数据 void sendSensorData() { String allData; for (int i = 0; i < 4; i++) { allData += sensorData[i]; } Wire.write(allData.c_str()); }
额外说明
- 从控端修正了浮点运算顺序,原代码中
5000为整数,会先做整数除法得到4,再乘以reading导致精度丢失,改为5000.0确保浮点运算准确性。 - 主控端扩大缓冲区并添加字符串结束符,避免数据溢出导致的乱码。
- 启动延迟解决了串口硬件未就绪时输出数据的乱码问题。
内容的提问来源于stack exchange,提问作者Karidus
相关产品推荐
相关产品推荐

