ESP8266 сбрасывает прерывания?

Я хочу использовать прерывания на своем ESP 8266 для мониторинга цифровых выходов счетчиков электроэнергии и воды.

Идея состоит в том, чтобы увеличить счетчик в ISR и в какой-то момент взять значение счетчика и установить счетчик обратно на 0 в функции loop() . Я вспомнил о критических секциях, noInterrupts() и interrupts(), а затем начал задаваться вопросом, будет ли выполняться ISR, когда код находится между noInterrupts() и interrupts(). Теоретически это должно быть так, потому что флаг прерывания в чипе будет поднят, и ISR будет вызван после того, как код выйдет из критической секции. Я написал программу для ее проверки, но мои выводы доказывают обратное.

#include <Arduino.h>
 
#define REPORT_TIME 5000
#define INTERRUPT_PIN D1

unsigned long base_time;

volatile unsigned int interrupt_counter = 0;


void IRAM_ATTR isr() {
  interrupt_counter++;
}

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

  // Прерывание будет FALLING EDGE
  pinMode(INTERRUPT_PIN, INPUT_PULLUP);
  pinMode(LED_BUILTIN_AUX, OUTPUT);
  digitalWrite(LED_BUILTIN_AUX, HIGH);
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isr, FALLING);

  base_time = millis();
}

bool written = false;

void loop() {

  if (!written)
  {
    written = true;
    for (int i = 0; i < 100; i++)
    {
      digitalWrite(LED_BUILTIN_AUX, LOW);
      digitalWrite(LED_BUILTIN_AUX, HIGH);
    }
  }
  

  unsigned long time_now = millis();
  if (time_now - base_time >= REPORT_TIME)
  {

    written = false;

    base_time = time_now;

    unsigned int interrupt_counter_local;

    //Охраняем критическую секцию
    noInterrupts();
    interrupt_counter_local = interrupt_counter;
    interrupts();

    digitalWrite(LED_BUILTIN_AUX, LOW);
    digitalWrite(LED_BUILTIN_AUX, HIGH);

    Serial.print("counter ");
    Serial.println(interrupt_counter_local);
    Serial.println();
  }
}

Используя провод, я подключил контакт встроенного светодиода к контакту прерывания, и в мониторе последовательного порта я увидел следующие значения:

counter 100
counter 201
counter 302

Когда я изменяю критическую секцию, чтобы она выглядела так:

noInterrupts();
interrupt_counter_local = interrupt_counter;
digitalWrite(LED_BUILTIN_AUX, LOW);
digitalWrite(LED_BUILTIN_AUX, HIGH);
interrupts();

Я ожидаю того же результата, что и выше, но значения следующие:

counter 100
counter 200
counter 300

Я что-то упустил или прерывания работают не так, как я ожидал?

, 👍2


1 ответ


1

После некоторых дополнительных экспериментов я обнаружил, что перемещение

digitalWrite(LED_BUILTIN_AUX, HIGH);

вне критической секции я получаю ожидаемый результат, поэтому я больше не заблокирован и, что более важно, чип не сбрасывает прерывание. Если кто-то знает, почему это не работает с моей первоначальной версией, буду рад услышать ответ.

,