Обработка нажатий тактовой кнопки.
Обычно первая программа программиста — выводит на экран строку “Hello word”, а эмбеддер мигает светодиодом, может ещё и кнопку прикрутить и с её помощью изменять состояние светодиода. Вот как раз про кнопку и хотел рассказать, обычно кнопку, которая что-либо переключает, называют тактовой кнопкой и подключают её по одной из схем, изображённых ниже.
На двух верхних схемах подтягивающие резисторы не изображены, но этот не значит, что их нет, просто они находятся внутри микросхемы.
Но гораздо более интересный вопрос заключается в том, как опрашивать кнопку, чтобы не пропускать нажатия? Вариант первый — в цикле опрашивать вывод, к которому подключена кнопка, этот способ будет работать пока программа небольших размеров (вкл-выкл светодиод), но по мере разрастания программы начнут пропускаться нажатия. Второй вариант, это настроить таймер, чтобы он переполнялся каждые 30 ms, а по переполнению возникало прерывание и в нём опрашивались выводы, к которым подключены кнопки, ну или кнопка. Почему время опроса 30 ms? Дело в том что кнопка подвержена дребезгу, а такой временной интервал между опросами, позволяет его не чувствовать, давайте рассмотрим этот момент подробнее.
Стрелки на картинке — это моменты возникновения прерываний, на верхней картинке изображен самый простой вариант развития событий, за счёт паузы между опросами, мы проскакиваем дребезг.
На средней картинке прерывание возникает в момент дребезга и как-будто бы кнопка не была нажата, но нас это не смущает, при следующем опросе кнопки фиксируем нажатие.
На нижней картинке прерывание снова возникает в момент дребезга, фиксируем нажатие и проскакиваем дребезг.
С отпусканием кнопки всё происходит по тому же сценарию и ещё если кнопка сильно дребезжит время между опросами можно увеличить.
Вот мы в прерывании, давайте рассмотрим варианты обработки нажатия. Первый выставляем флаг, что кнопка нажата, дальше в основном цикле проверяем его и там же сбрасываем, второй — заводим переменную и инкрементируем, её значение в прерывании если кнопка нажата, по отпусканию кнопки проверяем сколько натикало, то есть длительность удержания. Если натикало хотя бы один, то фиксируем короткое нажатие, если больше 10 — фиксируем длинное нажатие. Ещё раз поясню отличие первого способа от второго, в первом способе воздействие на систему происходит в момент нажатия кнопки, во втором — в момент отпускания, а какой способ выбрать решает сам программист, в зависимости от поставленной задачи.
Eщё можно попробовать реализовать двойное нажатие, и здесь мне видется два варианта, первый — после того как отпустили кнопку запускаем таймер и определённый промежуток времени ждём второго нажатия, если оно произошло, то фиксируем double_click. Второй способ — вести лог нажатий, то есть если кнопка была нажата и отпущена, то в нашей переменной будет храниться 0b00000010, если удерживается в течение 3 опросов, то 0b00000111, реализовать это просто: в прерывании сдвигаем значение переменной на одну позицию влево и в последний разряд записываем текущее состояние. Потом экспериментально(быстро нажимая два раза на кнопку) находим несколько значений переменной при двойном нажатии, например, у нас получилось 0b00110011, записываем это значение в double_click, теперь, для того чтобы определить двойное нажатие сравниваем значение нашей переменной с double_click. Первый вариант точно работает, а второй — просто мысли вслух.
На двух верхних схемах подтягивающие резисторы не изображены, но этот не значит, что их нет, просто они находятся внутри микросхемы.
Но гораздо более интересный вопрос заключается в том, как опрашивать кнопку, чтобы не пропускать нажатия? Вариант первый — в цикле опрашивать вывод, к которому подключена кнопка, этот способ будет работать пока программа небольших размеров (вкл-выкл светодиод), но по мере разрастания программы начнут пропускаться нажатия. Второй вариант, это настроить таймер, чтобы он переполнялся каждые 30 ms, а по переполнению возникало прерывание и в нём опрашивались выводы, к которым подключены кнопки, ну или кнопка. Почему время опроса 30 ms? Дело в том что кнопка подвержена дребезгу, а такой временной интервал между опросами, позволяет его не чувствовать, давайте рассмотрим этот момент подробнее.
Стрелки на картинке — это моменты возникновения прерываний, на верхней картинке изображен самый простой вариант развития событий, за счёт паузы между опросами, мы проскакиваем дребезг.
На средней картинке прерывание возникает в момент дребезга и как-будто бы кнопка не была нажата, но нас это не смущает, при следующем опросе кнопки фиксируем нажатие.
На нижней картинке прерывание снова возникает в момент дребезга, фиксируем нажатие и проскакиваем дребезг.
С отпусканием кнопки всё происходит по тому же сценарию и ещё если кнопка сильно дребезжит время между опросами можно увеличить.
Вот мы в прерывании, давайте рассмотрим варианты обработки нажатия. Первый выставляем флаг, что кнопка нажата, дальше в основном цикле проверяем его и там же сбрасываем, второй — заводим переменную и инкрементируем, её значение в прерывании если кнопка нажата, по отпусканию кнопки проверяем сколько натикало, то есть длительность удержания. Если натикало хотя бы один, то фиксируем короткое нажатие, если больше 10 — фиксируем длинное нажатие. Ещё раз поясню отличие первого способа от второго, в первом способе воздействие на систему происходит в момент нажатия кнопки, во втором — в момент отпускания, а какой способ выбрать решает сам программист, в зависимости от поставленной задачи.
Eщё можно попробовать реализовать двойное нажатие, и здесь мне видется два варианта, первый — после того как отпустили кнопку запускаем таймер и определённый промежуток времени ждём второго нажатия, если оно произошло, то фиксируем double_click. Второй способ — вести лог нажатий, то есть если кнопка была нажата и отпущена, то в нашей переменной будет храниться 0b00000010, если удерживается в течение 3 опросов, то 0b00000111, реализовать это просто: в прерывании сдвигаем значение переменной на одну позицию влево и в последний разряд записываем текущее состояние. Потом экспериментально(быстро нажимая два раза на кнопку) находим несколько значений переменной при двойном нажатии, например, у нас получилось 0b00110011, записываем это значение в double_click, теперь, для того чтобы определить двойное нажатие сравниваем значение нашей переменной с double_click. Первый вариант точно работает, а второй — просто мысли вслух.
Похожие статьи