niedziela, 1 kwietnia 2018

[9] ESP32 - Przerwania

Ten post chciałbym poświęcić na opisanie sposobu generowania przerwań w układzie ESP32 przez piny GPIO.

[Źródło: www.banggood.com]

Opis:


W przypadku tego mikrokontrolera, jak i właściwie każdego innego, działanie przerwań jest podobne.

Dostępne są przerwania systemowe jak i sprzętowe. Te drugie generowane są przez zewnętrzny układ jak przycisk czy UART.

Dla pinów w celu ustawienia przerwania wybiera się jeden z dostępnych opcji gpio_int_type_t:

  • GPIO_INTR_DISABLE - wyłączenie przerwań dla danego wyprowadzenia;
  • GPIO_INTR_POSEDGE - przerwanie uruchamiane zboczem narastającym;
  • GPIO_INTR_NEGEDGE - przerwanie uruchamiane zboczem opadającym;
  • GPIO_INTR_ANYEDGE - zbocze narastające jak i opadające wygeneruje przerwanie;
  • GPIO_INTR_LOW_LEVEL - niski poziom na linii generuje przerwanie;
  • GPIO_INTR_HIGH_LEVEL - poziom wysoki na linii generuje przerwanie;

W celu uruchomienia przerwania należy zainstalować odpowiednią usługę dla pinu, do którego ją przypiszemy. Możliwe jest utworzenie do 32 obsług przerwań dla dowolnych pinów.

  1. gpio_install_isr_service(0);


Po utworzeniu należy przypisać funkcję obsługującą przerwanie wraz z pinem:

  1. gpio_isr_handler_add(GPIO_PIN, ISR_Handler, NULL);

Ostatnim elementem są parametry, tutaj można nic nie przekazywać i zostawić wartość NULL.

Program:


Poniżej przedstawię przykładowy kod obsługujący przerwanie od przycisku. Można wykorzystać przycisk znajdujący się na płytce. Został on podłączony do pinu zerowego.  Zgodnie ze schematem pin został podłączony do masy. Oznacza to, że jego przyciśnięcie spowoduje podłączenie pinu do GND, czyli będzie się tam znajdował stan niski ( 0 V ). Z tego powodu najlepiej użyć wywołania przerwania od zmiany stanu z niskiego na wysoki ( GPIO_INTR_NEGEDGE ) gdy chcemy wywołać przerwanie w momencie naciśnięcia przycisku. Możliwe jest także wywołanie przerwania gdy przycisk zostanie zwolniony ( GPIO_INTR_POSEDGE ). 

Poniżej przedstawię przykładowy program obsługujące przerwanie od pinu zewnętrznego:

  1. #include <driver/gpio.h>
  2. #include <esp_log.h>
  3. #include <freertos/FreeRTOS.h>
  4. #include <freertos/queue.h>
  5. #include <freertos/task.h>
  6.  
  7. #include "sdkconfig.h"
  8.  
  9. bool diodeStatus = false;
  10. static char nameTag[] = "interupt";
  11. static QueueHandle_t q1;
  12.  
  13.  
  14. static void interruptHandler(void *args)
  15. {
  16.     gpio_num_t gpio;
  17.     gpio = 0;
  18.     diodeStatus = !diodeStatus;
  19.     gpio_set_level(15, diodeStatus);
  20.     xQueueSendToBackFromISR(q1, &gpio, NULL);
  21. }
  22.  
  23. void app_main()
  24. {
  25.     ESP_LOGD(nameTag, ">> Interrupt");
  26.     gpio_num_t gpio;
  27.     q1 = xQueueCreate(10, sizeof(gpio_num_t));
  28.  
  29.     gpio_config_t gpioConfigurate;
  30.     gpioConfigurate.pin_bit_mask          = GPIO_SEL_0;
  31.     gpioConfigurate.mode                  = GPIO_MODE_INPUT;
  32.     gpioConfigurate.pull_up_en            = GPIO_PULLUP_DISABLE;
  33.     gpioConfigurate.pull_down_en          = GPIO_PULLDOWN_ENABLE;
  34.     gpioConfigurate.intr_type             = GPIO_INTR_NEGEDGE;
  35.     gpio_config(&gpioConfigurate);
  36.  
  37.     gpio_install_isr_service(0);
  38.     gpio_isr_handler_add(0, interruptHandler, NULL);
  39.     while(1) {
  40.         BaseType_t confQue = xQueueReceive(q1, &gpio, portMAX_DELAY);
  41.     }
  42.     vTaskDelete(NULL);
  43. }

W celu realizacji przerwania można używać kolejki czy semafora. Tutaj do pinu podpinamy funkcje zmieniającą stan diody.

Dokumentacja: [1] [2]