3.10. GPIO-вход¶
Считывание переключателя (или любого цифрового сигнала) с вывода GPIO снова проходит через machine.Pin, на этот раз сконфигурированный как вход. Интерфейс симметричен выходу: настройте режим, а затем либо опрашивайте значение вывода в основном цикле, либо зарегистрируйте обработчик прерывания, который срабатывает при изменении значения.
3.10.1. Конфигурирование входа¶
Передайте Pin.IN в конструктор и, опционально, подтягивающий резистор:
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
Это конфигурирует P0 как вход с включённым внутренним подтягивающим к питанию резистором MCU. Если к выводу ничего не подключено, подтяжка удерживает его на высоком уровне; замыкание переключателя от вывода на землю переводит его в низкий уровень.
3.10.2. Считывание значения¶
value() без аргументов возвращает текущее состояние – 0 для низкого, 1 для высокого уровня:
if button.value() == 0:
print("button pressed")
else:
print("button released")
В шаблоне основного цикла опрос выглядит так:
while True:
if button.value() == 0:
do_action()
time.sleep_ms(50)
Пауза в 50 мс не даёт циклу выполняться на полной загрузке CPU.
3.10.3. Ввод по прерыванию¶
Опрос работает, но каждая итерация основного цикла расходует время CPU. Для входов, которые меняются редко – нажатие кнопки раз в минуту, сигнал тревоги – irq() регистрирует обработчик, который выполняется только при изменении вывода.
Обработчик выполняется в контексте прерывания, что ограничивает то, что он может делать:
Никакого выделения памяти. Создание новых объектов – списков, строк, исключений, форматированных строк – может завершиться сбоем внутри ISR, потому что куча заблокирована. Заранее выделяйте любые буферы, нужные обработчику, на уровне модуля.
Никакой долгой работы. Обработчик должен передать управление и вернуться. Трата реального времени внутри ISR задерживает всё остальное (другие прерывания, основной цикл, USB-трафик).
Никакого вывода в напряжённой ISR.
print()выделяет память, блокируется на UART и является одной из самых дорогих операций, которые может выполнить обработчик.
Стандартный шаблон состоит в том, что ISR планирует реальную работу через micropython.schedule(), который ставит функцию в очередь на выполнение в основном контексте в следующей безопасной точке:
import micropython
def handle_press(pin):
print("button pressed")
def on_press(pin):
micropython.schedule(handle_press, pin)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
ISR состоит из одной строки: поставить функцию обратного вызова в очередь и вернуться. handle_press затем выполняется в обычном контексте, где выделение памяти, print() и медленный ввод-вывод снова безопасны.
Аргумент trigger выбирает, какой фронт вызывает срабатывание:
Pin.IRQ_FALLING– с 1 на 0.Pin.IRQ_RISING– с 0 на 1.Pin.IRQ_FALLING|Pin.IRQ_RISING– оба фронта.