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

ESP8266复用器逻辑外部化后报错及显示异常求助

故障原因分析及修复方案

核心故障原因

1. SH1106Wire对象副本引发资源冲突

DisplayService::display()方法返回的是全局displayObject的值副本,而SH1106Wire类内部持有I2C总线操作句柄。每次返回副本时会触发对象拷贝构造,销毁副本时又会释放相关资源,反复的拷贝-销毁会导致I2C总线资源混乱,最终触发ESP8266硬件看门狗复位(报错里的rst cause:2就是硬件看门狗复位)。

2. 重复调用init()方法导致通信异常

每次调用display()都执行displayObject.init(),SH1106的init()会向显示屏发送初始化指令,重复初始化会干扰I2C总线通信,导致显示屏响应异常,出现偶尔闪烁的情况。

3. 初始化流程缺失

setup()函数中未初始化I2C总线(Wire.begin())和串口,封装类后总线初始化不明确,会加重通信异常。

修复后的代码

修改DisplayService_h

#ifndef DisplayService_h
#define DisplayService_h
#include "SH1106Wire.h"
class DisplayService {
   public:
    DisplayService();
    // 返回引用,避免拷贝对象
    SH1106Wire& display(u_int8_t displayNumber);
   private:
    SH1106Wire displayObject; // 改为成员变量,而非全局
    void changeDisplay(u_int8_t displayNumber);
};
#endif

修改DisplayService.cpp

#include "Arduino.h"
#include "SH1106Wire.h"
#include <Wire.h>
#include "DisplayService_h"

DisplayService::DisplayService() : displayObject(0x3C, SDA, SCL) {
    Wire.begin(); // 初始化I2C总线
    displayObject.init(); // 仅初始化一次显示屏
}

SH1106Wire& DisplayService::display(u_int8_t displayNumber){
    Serial.println(displayNumber);
    this->changeDisplay(displayNumber);
    // 不再重复调用init()
    return displayObject;
}

void DisplayService::changeDisplay(u_int8_t displayNumber){
    Wire.beginTransmission(0x70);  // TCA9548A地址
    Wire.write(1 << displayNumber); // 选择对应通道
    Wire.endTransmission();
    // 添加短暂延迟确保多路复用器切换完成
    delay(10);
}

修改main.cpp

#include <Arduino.h>
#include <services/displayservice/DisplayService_h>
#include "SH1106Wire.h"

DisplayService displayService;

void setup() {
    Serial.begin(115200); // 初始化串口用于调试
}

void loop() {
    for (int i = 2; i <= 6; i++) {
       // 用引用接收,避免拷贝对象
       SH1106Wire& display = displayService.display(i);
       delay(2000);
       display.clear();
       display.flipScreenVertically();
       display.setFont(ArialMT_Plain_24);
       display.setTextAlignment(TEXT_ALIGN_CENTER);
       display.drawString(64, 20, "TEST");
       display.display();
       delay(500);
    }
}

额外注意事项

  • TCA9548A通道切换后添加10ms左右延迟,确保多路复用器稳定切换到目标通道。
  • 避免在循环中频繁创建和销毁SH1106Wire对象,复用同一个对象可减少资源开销和通信异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 03:05:48