【问题标题】:ESP32 can't display text on OLED from Timer ISRESP32 无法通过 Timer ISR 在 OLED 上显示文本
【发布时间】:2021-02-02 18:23:13
【问题描述】:

问题

我有一个使用 Adafruit_SSD1306 库连接的带有 I2C OLED 的 ESP32 T-call SIM800L。在设置或循环中调用 displayText() 函数时它工作得很好,虽然我有一个设置为 1Hz 的定时器中断,我试图在 OLED 上显示一条消息,但它不起作用。 ISR 本身确实有效,我有一个计数变量,它在每次中断时递增,我将它打印到串行监视器(我知道你不应该真的在 ISR 中做串行的东西,但它仍然有效)所以 ISR 肯定会中断正确。奇怪的是,我发誓我之前有它工作过(在 ISR 中显示),所以我相信这是可能的。我尝试删除 ISR 中的所有其他内容,只包括显示功能,但没有成功。

非常感谢任何帮助

代码:

#include <Adafruit_SSD1306.h> //OLED
#include <Adafruit_GFX.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

volatile int count = 0;

void setupDisplay () 
{

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) // Address 0x3C for 128x32
  
  { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever

  }
}

void displayText(int count) 
{

  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print(count);
  display.display();      // Show initial text

}

///* create a hardware timer */
hw_timer_t * timer = NULL;

void IRAM_ATTR onTimer()
{
count++;
Serial.println(count);
//displayText(count);


  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Display from ISR");
  display.display();      // Show initial text

}

void setup() 
{
  Serial.begin(115200); 

  setupDisplay();
  displayText(count);

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
  Serial.println("start timer");
}

void loop()
{

}

串行监视器打印输出

start timer
1
2
3
4
5
6
7
8
9
10

【问题讨论】:

    标签: arduino esp32 arduino-c++


    【解决方案1】:

    你在中断处理程序中做的太多了。

    中断处理程序不应调用高级函数,除非您知道它们是可重入的 - 也就是说,它们在操作硬件或数据结构时锁定中断以保持一致性 - 并且它们可以在 RAM 中执行(已从闪存中复制,这是 IRAM_ATTR 修饰符所保证的)。

    中断处理程序也应该运行尽可能短的时间,因为它们会阻止 ESP32 处理其他中断。

    如果您不执行这些操作,您的程序有时可能会起作用。当您对其进行小的更改时,它也可能会随机停止工作或开始崩溃或表现出我们喜欢称之为“未定义行为”的情况。

    不要调用Serial.println() 或您的任何display 方法,而是设置volatile boolean 标志以指示有工作要做,并在loop() 中完成工作。

    试试这个:

    volatile boolean work_to_be_done = false;
    
    void IRAM_ATTR onTimer()
    {
    count++;
    work_to_be_done = true;
    }
    
    void loop()
    {
      if(work_to_be_done)
      {
        Serial.println(count);
        //displayText(count);
    
    
        display.clearDisplay();
        display.setTextSize(1); // Draw 2X-scale text
        display.setTextColor(SSD1306_WHITE);
        display.setCursor(0, 0);
        display.print("Display from ISR");
        display.display();      // Show initial text
    
        work_to_be_done = false;
      }
    }
    

    您也可以写loop() 来检测count 已更改,但我更喜欢维护一个表明有事情要做的标志的清晰性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 2022-07-11
      • 2019-04-19
      相关资源
      最近更新 更多