W poprzednim artykule opisałem przerwania czasowe w ESP32. Tym razem krótka informacja dotycząca zastosowania przerwań GPIO.

Budując układ często musimy odczytać stan GPIO. Może to być wciśnięcie przycisku klawiatury sterującej, odczyt stanu krańcówki, czy zliczanie impulsów jakiegoś czujnika. Czynności te muszą być wykonane niezwłocznie, niezależnie od wykonywania bieżącego programu. Do tego można wykorzystać oczywiście przerwania. ESP32 umożliwia wywołanie przerwania z wykorzystaniem dowolnego z pinów GPIO. Dodatkowo możemy określić rodzaj akcji, która wywoła przerwanie. Do dyspozycji mamy 5 możliwości:

Stan Opis
LOW Przerwanie wywoła stan niski (LOW)
HIGH Przerwanie wywoła stan wysoki (HIGH)
CHANGE Przerwanie wywoła dowolna zmiana stanu
FALLING Przerwanie wywoła opadające zbocze (zmiana z HIGH na LOW)
RISING Przerwanie wywoła narastające zbocze (zmiana z LOW na HIGH)

Do podłączenia funkcji obsługi przerwania do konkretnego złącza GPIO służy funkcja attachInterrupt().

attachInterrupt(GPIOPin, ISR, Mode);

GPIOPin to numer wykorzystywanego pinu GPIO, ISR to nazwa funkcji obsługi przerwania, a Mode to jedna z wartości z tabeli powyżej określająca sposób wywołania przerwania. Poniżej znajduje się struktura funkcji obsługi przerwania.

void IRAM_ATTR ISR() {
    Instrukcje;
}

Funkcja niczego nie zwraca (void), nie przekazujemy też żadnych parametrów. Atrybut IRAM_ATTR jest niezbędny dla kompilatora, żeby umieścił kod obsługi przerwania w odpowiednim miejscu w pamięci ESP32. Nazwa funkcji ISR może zostać zastąpiona przez dowolną inną nazwę zgodną z nazewnictwem stosowanym w C++. Do odłączenia przerwania od GPIO służy funkcja detachInterrupt(). Wykorzystujemy ją w sytuacji, gdy w czasie wykonywania programu chcemy zmienić funkcję obsługującą przerwanie, lub nie chcemy dalej korzystać z przerwania wywoływanego przez GPIO.

detachInterrupt(GPIOPin);

Poniżej przykładowy kod programu zliczającego impulsy z GPIO. Przerwanie wywoływane jest zboczem narastającym.

#define LICZNIK_PIN 14                    
int licznik=0;
//funkcja obsługi przerwania
void IRAM_ATTR zlicz() {    
  licznik++;
}
 
void setup() {
  Serial.begin(115200);
  attachInterrupt(LICZNIK_PIN, zlicz, RISING);
  Serial.println("Rozpoczynam zliczanie");
}
 
void loop() {
  //główna pętla przesyła co 3 sekundy komunikat
  Serial.println("Główna pętla blokowana na 3 sekundy");
  Serial.print("Stan licznika: ");
  Serial.println(licznik);
  delay(3000);
}

Wnioski

Obsługa przerwań GPIO w układach ESP nie jest czymś skomplikowanym. Wystarczy kilka linii kodu i wszystko działa. Należy pamiętać o kilku podstawowych sprawach dotyczących przerwań. W funkcji obsługi przerwania nie można wykonywać zbyt czasochłonnych operacji. Może to negatywnie wpłynąć na wykonywanie całego programu. W przypadku przerwań z GPIO stosujemy najczęściej narastające lub opadające zbocze (wywołujemy przerwanie zmianą stanu). Wywoływanie przerwania stanem niskim lub wysokim może doprowadzić do niekontrolowanego cyklicznego wywoływania funkcji obsługi przerwania. Wywołanie przerwania konkretnym stanem wykorzystujemy wyłącznie wtedy, gdy dokładnie wiemy co chcemy uzyskać.