Если на множественное нажатие надо реагировать 1 раз, то какой-то триггер надо городить. Настройки таймера 2 под ATmega328 16 МГц, в makefile. Под другую конфигурацию как-то по другому надо.
Насчёт двойного клика. На одном форуме как-то было обсуждение обработки кнопок. Навешивать некоторые функции на модуль обработки клавиш, думаю неоптимально, с точки зрения универсальности. Модуль кнопок должен опрашивать кнопки, определять обычные нажатия, удержание, автоповтор, отпускание кнопок. Подсчет количества нажатий должно вестись в соответствующем программном модуле, который принимает события от модуля кнопок и коды кнопок. В этом случае соблюдается универсальность применения модуля обработки кнопок. Да и как бы это и логично. Двойное и так далее нажатия кнопок требование конкретного проекта, а не модуля обработки кнопок. Мало того. В отдельных случаях, удержание и автоповтор тоже можно разнести. На модуль обработки кнопок оставить некий общий принцип. Скажем, минималка удержания (особые требования реализовать уже в каждом конкретном проекте). То же касается и автоповтора. Пояснение, минимальное время удержания, скажем, 500 мс, время автоповтора, 25 мс. Удержание, автоповтор могут не потребоваться. В разных проектах разные требования ко времени удержания, автоповтора. Конечно же, окончательное решение на своих проектах каждый принимает сам. Что оптимальнее и целесообразно
Для ТС. Двойное и более нажатия. Реализация вне модуля опроса кнопок. В модуле приема событий кнопок создаётся переменная счётчик. Алгоритм. В случае события нажатия кнопок разбираем, какая кнопка нажата. Если на эту кнопку ведётся подсчет, инкремент переменной счётчика. Далее сравнение и соответствующее действие.
Подсчет количества нажатий должно вестись в соответствующем программном модуле, который принимает события от модуля кнопок и коды кнопок. В этом случае соблюдается универсальность применения модуля обработки кнопок. Да и как бы это и логично. Двойное и так далее нажатия кнопок требование конкретного проекта, а не модуля обработки кнопок. Мало того. В отдельных случаях, удержание и автоповтор тоже можно разнести. На модуль обработки кнопок оставить некий общий принцип. Скажем, минималка удержания (особые требования реализовать уже в каждом конкретном проекте).
Не удобно, я обычно стараюсь запихнуть всего побольше, но с возможностью выбора, правда на С такое красиво сделать вряд ли получится:
Код:
using pins = PinList<PC13, PA1, PB0, PB10>; Buttons<pins> buttons;
Это простейший случай, ловим только обычные нажатия для всех кнопок.
using pins = PinList<PC13, PA1, PB0, PB10>; Buttons<pins, conf> buttons;
А тут я включил очередь, что помимо прочего позволяет вызывать update() из прерывания, далее для трех кнопок ловим обычные нажатия, для двух из них включен автоповтор, а четвертая реагирует только на отпускания и длинные нажатия. Все эти параметры передаются в класс как константы, они даже во флеше не хранятся и если, допустим, сделать longMask нулевой, то весь код за обработки длинных нажатий выпилится потому что в классе десяток if constexpr:
Код:
if constexpr (longMask) { auto diff = (prevLongPressed ^ current); state.longPressed = diff & current & longMask; prevLongPressed = current; }
И так со всем, если очередь не используется, то вместо класса подставится bool и нигде не используемая булевая переменная тоже выпилится.
To Reflector. Задача модуля кнопок выдать события нажатия, отжатия, удержания и повтора. Коды кнопок. В большинстве случаев в девайсах работает принцип обработка всех кнопок, как одну. Сочетания или одновременное нажатие кнопок используется не всегда. Подсчет количества нажатий это уже задача конкретного проекта. Именно по этому я говорил про универсальность. Берешь свои готовые либы и чуток подпиливаешь под нужный проект. В большинстве случаев просто дефайнами переназначаешь пины мк. В вашем же случае это всегда глубокая переработка.
To ARV. Поддерживаю. Очередь кнопок не всегда нужна. Далеко не всегда. Это уже попахивает более серьезными проектами и микроконтроллерами. Скорее, линуксом.
Очереди, структуры в очередях... Как обычно, забыли о разделе, где идет обсуждение: в большинстве популярных AVR на очередь кнопок половина ОЗУ уйдет
Не очередь, а опциональная и выключенная по умолчанию очередь. А структура у меня на STM32, там 32 бита в регистре вернуть можно, на AVR никто так делать не заставляет.
To Reflector. Задача модуля кнопок выдать события нажатия, отжатия, удержания и повтора. Коды кнопок. В большинстве случаев в девайсах работает принцип обработка всех кнопок, как одну. Сочетания или одновременное нажатие кнопок используется не всегда. Подсчет количества нажатий это уже задача конкретного проекта. Именно по этому я говорил про универсальность. Берешь свои готовые либы и чуток подпиливаешь под нужный проект. В большинстве случаев просто дефайнами переназначаешь пины мк. В вашем же случае это всегда глубокая переработка.
Ничего не понял, я же показал код в котором все конфигурируется в одном месте, где там глубокая переработка? То весь код, минимум две строки, дальше нужно вызвать init(), update и получить состояние кнопок, т.е. еще 3 строки. Сам класс живет в хедере и никогда не меняется, никаких дефайнов и т.д. больше нигде нет.
Имхо, на си более-менее красиво получается, если писать отдельно систему событий и их обработку. А генератором событий делать, что угодно. Тогда верхний уровень пользуется только функцией get_event, а уж эта функция может и очередь обрабатывать, и приоритеты... А готовить данные для этой функции можно, как угодно: по таймеру кнопок, по прерыванию USART и т.п. Там же где-то внутри можно и двойные клики делать, и одновременные нажатия...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
А чего стоит оставить своё мнение при себе? Или, требуется _всех_ убедить в правильности своего мнения? Я прекрасно понимаю, о чем вы пишите. Только смысла в ваших конструкциях не вижу. Переиначивая, весь ваш бред - бессмысленная хня. Не умеешь писать - не пиши.
// обработчик прерывания по переполнению таймера 0 ISR(TIMER0_OVF_vect) { //=========== опрос первой кнопки ============= if (~PINC&(1<<PC0)) // если на ПИНе 1 { if (bit.flag_1==0) //если флаг =0 , то считаем до 120 иначе до 61 { if (button1_count<120) button1_count++;//Счетчик будет считать до 120 (~2с) if (bit.flag_2==1) //Если флаг =1 включаем репит клик (быстрый инкримент) { if(button1_count==118) button1_count=112; button_click=0; } } else { if (button1_count<61) button1_count++;//Счетчик будет считать до 61 (~1с) } } else { if ((button1_count>5) && (button1_count<30)) bit.but_1=1; //Короткий клик if ((button1_count>29) && (button1_count<=61)) bit.but_1=2; //Средний клик if ((button1_count>61) && (button1_count<=120))bit.but_1=3; //Длинный клик button1_count=0; } //===========Опрос второй кнопки =========== if (~PINC&(1<<PC1)) // если на ПИНе 1 { if (bit.flag_1==0) //если флаг =0 , то считаем до 120 иначе до 61 { if (button2_count<120) button2_count++;//Счетчик будет считать до 120 (~2с) } else { if (button2_count<61) button2_count++;//Счетчик будет считать до 61 (~1с) } } else { if ((button2_count>5) && (button2_count<30)) bit.but_2=1; //Короткий клик if ((button2_count>29) && (button2_count<61)) bit.but_2=2; //Средний клик if ((button2_count>61) && (button2_count<=120)) bit.but_2=3; //Длинный клик button2_count=0; } ////===========Опрос третьей кнопки =========== if (~PINC&(1<<PC2)) // если на ПИНе 1 { if (bit.flag_1==0) //если флаг =0 , то считаем до 120 иначе до 61 { if (button3_count<120) button3_count++;//Счетчик будет считать до 120 (~2с) } else { if (button3_count<61) button3_count++;//Счетчик будет считать до 61 (~1с) } } else { if ((button3_count>5) && (button3_count<30)) bit.but_3=1; //Короткий клик if ((button3_count>29) && (button3_count<=61)) bit.but_3=2; //Средний клик if ((button3_count>61) && (button3_count<=120)) bit.but_3=3; //Длинный клик button3_count=0; }
if (~PINC&(1<<PC5)) bit.flag_1=1; else bit.flag_1 =0; if (~PINC&(1<<PC4)) bit.flag_2=1; else bit.flag_2 =0;
} }
Код:
#ifndef MAIN_H_ #define MAIN_H_ struct my_button { unsigned char but_1:2; //Битовый код 1ой кнопки 0-3 unsigned char but_2:2; //Битовый код 2ой кнопки 0-3 unsigned char but_3:2; //Битовый код 3ей кнопки 0-3 unsigned char flag_1:1; // Флаг разрешающий клик двух кнопок unsigned char flag_2:1; // Флаг разрешающий инкремент по длинному клику }; struct my_button bit;
#endif /* MAIN_H_ */
Но проблема в том, что в Протеусе, при отпускании кнопки, условия Элс выполняются через раз. Счетчик сбрасывается в ноль стабильно, а вот присвоения значений bit.but_*** происходит как то не стабильно. Подскажите, почему так происходит. Думал про дребезг при отпускании, но раз счетчик обнуляется, то программа прорходит по всем сравнениям Ифф.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 29
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения