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
Я что-то упустил или прерывания работают не так, как я ожидал?
@Plamen Peev, 👍2
1 ответ
После некоторых дополнительных экспериментов я обнаружил, что перемещение
digitalWrite(LED_BUILTIN_AUX, HIGH);
вне критической секции я получаю ожидаемый результат, поэтому я больше не заблокирован и, что более важно, чип не сбрасывает прерывание. Если кто-то знает, почему это не работает с моей первоначальной версией, буду рад услышать ответ.
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Постоянная частота дискретизации АЦП на ESP8266 или ESP32
- Серийное прерывание
- Отключить прерывания при выполнении важных действий?
- Влияет ли `millis()` на длинные ISR?
- Как прервать функцию цикла и перезапустить ее?
- Как избежать электромагнитных помех на входе ESP32
- Аппаратное прерывание срабатывает случайным образом