narod stream
430 subscribers

ESP32 Урок 5. GPIO interrupt

В прошлом уроке нам удалось попробовать использование порта ввода-вывода на вход.

Только работали мы с кнопкой, отслеживая её состояние в неком цикле, что накладывает ряд ограничений на работу всей программы. Для этого и придумано следить за состоянием портов именно посредством прерываний. Как это всё работает, мы уже неоднократно видели, например в аналогичном уроке для ESR8266 и уроках для работы с другими контроллерами.

Мы знаем также, что внешние прерывания обрабатываются разные, вернее они работают по разным событиям (нарастание,  спад и т.д.). Есть также универсальные прерывания, которые отслеживают и то и это. ESP32 в этом плане также не исключение и в нём это всё есть. И не только это. В технической документации (Technical Reference Manual) есть описание регистра GPIO_PINn_REG, в котором есть битовое поле, отвечающее за настройку типов прерываний для порта ввода-вывода

ESP32 Урок 5. GPIO interrupt

Вот описание установки значения в данном поле:

GPIO_PINn_INT_TYPE Interrupt type selection: (R/W) 0: GPIO interrupt disable; 1: rising edge trigger; 2: falling edge trigger; 3: any edge trigger; 4: low level trigger; 5: high level trigger.

Третий тип установки отслеживает и фронт и спад сигнала.

Поэтому нам никак нельзя данные возможности обойти и этим не воспользоваться. Тем более что с данными прерываниями мы не работали в операционной системе реального времени FreeRTOS.

Так как мы будем использовать не один тип изменения сигнала на ножке, давайте подключим две кнопки, одну по-прежнему к GPIO4, а другую — к GPIO5

ESP32 Урок 5. GPIO interrupt

Проект мы за основу возьмём из прошлого урока с именем BUTTON01 и дадим ему имя EXTI01.

Откроем наш новый проект в Espressif IDE и внесём некоторые изменения в файл конфигурации Kconfig.projbuild.

Во второй пункт мы добавим номер кнопки, так как их будет два

config BUTTON_GPIO_1

int "Button GPIO1 number"

range 0 48

default 4

help

GPIO number Button 1.

Ниже добавим ещё один пункт для второй кнопки

config BUTTON_GPIO_2

int "Button GPIO2 number"

range 0 48

default 5

help

GPIO number Button 2.

Обратите внимание, что номер порта по умолчанию тоже будет другой.

Попробуем собрать проект, и сконфигурировать его. При сборке скорей всего будет ошибка на изменение имени переменной, не обращаем внимание на это

ESP32 Урок 5. GPIO interrupt

Из тела функции app_main файла main.c удалим весь код, кроме бесконечного цикла, останется вот это

Теперь у нас, конечно же, код соберётся.

Добавим в данную функцию объявление переменой для счётчика циклов

Сегодня мы не будем для изменения каждого параметра порта ввода-вывода использовать отдельную функцию, а будем использовать для этого специальную структуру.

Поэтому создадим переменную типа такой структуры

Объявим несколько макросов — один для маски ножки выхода, а другой для маски ножек входа, а также макрос для настройки флага прерываний

Вернёмся в функцию app_main и проинициализируем поля переменной структуры настройками для ножки, работающей на выход

Применим данные настройки с помощью специальной функции

Теперь заполним поля для ножек, работающих на вход, и также применим настройки. Поля, которые не меняются, повторно инициализировать не надо

Мы хотим, чтобы типы прерываний были разные, а у нас присвоился один и тот же тип для обеих ножек при помощи присвоения значения перечислимого типа GPIO_INTR_POSEDGE полю intr_type.

Мы можем определённой ножке порта применить другой тип при помощи функции. Так и поступим

Далее перед нами стоит задача добавить обработчик прерываний, в котором мы и будем их отслеживать и из которого при помощи очереди будем передавать в другую задачу, где и будет код реакции на данные события. Поступаем мы так потому, что в обработчике прерываний должен быть минимальный код.

Добавим глобальную переменную для очереди

Также подключим библиотеку для работы с очередями

Создадим очередь в app_main

Выше функции app_main добавим функцию задачи, которая будет выводить в порт информацию по событиям прерываний

Здесь из очереди забирается номер ножки порта и выводится в терминал, а также заодно выводится состояние данной ножки.

Создадим данную задачу в app_main с высоким приоритетом. Хотя, в принципе, это не очень высокий приоритет. Мы в этом убедимся, когда будем выводить список задач со значениями их приоритетов и номерами ядра, в котором выполняется каждая задача

Включим прерывания

Мы можем назначить один и тот же обработчик прерывания на оба входа. Добавим функцию для него выше функции task1

В данном обработчике мы при помощи параметра передаём в очередь номер ножки порта. Стоит обратить внимание, что для передачи в очередь из обработчиков прерываний используется несколько другая функция, нежели из обычных задач.

В функции app_main объявим наш обработчик для каждой ножки

В бесконечном цикле выведем значение счётчика, который будет считать каждый цикл, заодно проинкрементировав его, и установим значение ножки светодиода в зависимости от чётности счётчика

Ну вот, в принципе, и всё. Соберём код, прошьём контроллер и запустим терминал. Терминал мы сегодня запустим прямо в среде Espressif IDE. Если у кого он ещё не добавлен в окно ввода-вывода, то делается это посредством выбора пункта меню Window->Show View->Terminal

ESP32 Урок 5. GPIO interrupt

Запускаем терминал, настраиваем порт и видим как наращивается наш счётчик. В такт с этим мигает светодиод на плате

ESP32 Урок 5. GPIO interrupt
ESP32 Урок 5. GPIO interrupt

Нажмём на кнопку 1 и, так как кнопка прижимает ножку на общий провод, то у нас в терминале отобразится уровень 0

ESP32 Урок 5. GPIO interrupt

ESP32 Урок 5. GPIO interrupt

Отожмём кнопку, разорвав цепь, и увидим, что на ножке у нас теперь уровень 1

ESP32 Урок 5. GPIO interrupt

Также мы в сообщении видим номер ножки порта.

Нажмём теперь кнопку 2

ESP32 Урок 5. GPIO interrupt

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

ESP32 Урок 5. GPIO interrupt

Отожмём кнопку и вот результат

ESP32 Урок 5. GPIO interrupt

Таким образом, на данном уроке мы научились отслеживать состояние ножек порта посредством обработки событий в прерываниях. Также мы научились работать с информацией из виртуального порта прямо в среде разработки Espressif IDE.

Всем спасибо за внимание!

Оригинал статьи находится здесь.

<<Предыдущий урок | Следующий урок>>

Исходный код

Недорогие отладочные платы ESP32 можно купить здесь: Недорогие отладочные платы ESP32

Видео в Дзен

Видео в Youtube