Предположим, нам надо чтобы Ардуино выполняла какие-то действия периодически. Опрашивала клавиатуру, датчики, выводила данные на дисплей или в монитор и пр. Надо чтобы это выполнялось «фоном», прозрачно для основной программы.
Программируя на «чистом» AVR это сделать легко и просто. Берём таймер и программируем его формировать прерывания с заданным периодом. Но в Wiring (языке программирования Ардуино) нет штатных средств доступа к таймерам! Конечно, ничто не мешает делать в программе вставки на чистом Си и писать напрямую в соответствующие регистры процессора. Но это как бы нарушает принципы простоты и переносимости, заложенные в платформу.
Попробуем это обойти.
Ардуино может использовать timer/counter 2 для издавания звуков. Функция tone формирует меандр звуковой частоты на выбранном выходе. Завернём этот выход на цифровой вход 2 или 3, которые могут использоваться функцией attachInterrupt для реагирования на внешние события. Т.е. поставим перемычку. И загрузим скетч:
Открыв монитор порта, видим что переменная обновляется.
Идём дальше. Вспомним что МК AVR позволяют назначить прерывание не только на вход, но и … на выход! Т.е. мы выводим нечто и заодно следим за этим чем-то. И если что-то с этим чем-то происходит 🙂 например, «1» меняется на «0», можно вызвать прерывание и это событие отметить обработать. Пробуем:
Работает! Т.е. можно задействовать только один порт вместо двух и обойтись без перемычки.
Есть у этого метода ограничения. Во-первых, tone исключает возможность использования ШИМ на выходах 3 и 11. Во-вторых, частота tone не может быть ниже 31 Гц. Если прерывания нужны реже, придётся делать программный делитель в обработчике прерываний.
Существует пара библиотек: раз и два, которые преодолевают ограничение с частотой и позволяют конфигурировать таймер более гибко.