You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino中I2C OLED显示屏打印异常问题求助

问题排查与修复

核心错误点

  • 字符串缺少结束符\0:display.println依赖C风格字符串的结束符确定显示长度,原代码接收字符后未手动添加\0,会导致函数读取内存中随机数据,引发显示偏移或乱码。
  • 数组越界风险:cnt变量无上限检查,当串口接收字符数超过buff长度(10)时,会覆盖其他变量内存,导致程序逻辑混乱,后续无法正常显示。
  • 未处理串口接收结束标志:原代码只要串口有数据就触发显示,未等待完整字符串(比如输入的换行符),可能显示不完整内容,且多次触发显示逻辑。
  • 误用println:println会自动添加换行符,导致第二次显示时Y轴偏移,破坏固定位置的显示逻辑。

修复后的代码

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);
char buff[10] = {0}; // 初始化全0,确保默认包含结束符
int cnt = 0;
int alpha = 0;

void setup()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);
  Serial.begin(9600);
}

void loop()
{
  while (Serial.available()) {
    char a = Serial.read();
    // 以换行符作为字符串结束标志,同时限制cnt不超过数组长度-1(预留结束符位置)
    if (a == '\n' || cnt >= sizeof(buff) - 1) {
      buff[cnt] = '\0'; // 手动添加字符串结束符
      alpha = 1;
      cnt = 0; // 重置计数器
    } else {
      buff[cnt++] = a;
    }
  }

  if (alpha == 1) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.setTextSize(1);
    display.print(buff); // 用print代替println,避免自动换行
    display.display();
    alpha = 0;
    memset(buff, 0, sizeof(buff)); // 清空缓冲区,避免旧数据残留
  }
}

修复说明

  1. 添加字符串结束符:在接收完完整字符串(或达到数组上限)时手动添加\0,确保display.print能正确识别字符串长度。
  2. 数组边界检查:限制cnt不超过sizeof(buff)-1,预留结束符位置,彻底避免数组越界。
  3. 处理结束标志:以换行符\n作为字符串接收完成的标志,确保只有完整输入才触发显示。
  4. 替换println为print:取消自动换行逻辑,固定显示位置在(0,0)。
  5. 清空缓冲区:每次显示后用memset清空buff,避免旧数据干扰下一次显示。

内容的提问来源于stack exchange,提问作者Rj Choudhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:16:24