Форум РадиоКот https://radiokot.ru/forum/ |
|
Обработка кнопок, EXTI[0] https://radiokot.ru/forum/viewtopic.php?f=59&t=195560 |
Страница 1 из 4 |
Автор: | aleksey chilov [ Пн ноя 11, 2024 17:16:30 ] |
Заголовок сообщения: | Обработка кнопок, EXTI[0] |
Добрый вечер кому как. Подскажите пожалуйста варианты обработки кнопочек, для меню. Спасибо. |
Автор: | Аlex [ Пн ноя 11, 2024 18:51:07 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Покажите свои варианты, а мы оценим ![]() |
Автор: | BOB51 [ Пн ноя 11, 2024 19:36:46 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Вариантов огромное множество. Зависит от схемы, компилятора и идеи самого устройства. ![]() |
Автор: | Martian [ Вт ноя 12, 2024 10:39:49 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет? |
Автор: | AlanDrakes [ Вт ноя 12, 2024 11:26:19 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Кто как, а я опрашиваю кнопки в основном потоке, когда код ничего не делает (внутри while (1) { .... __WFI(); } ) обычно после выхода из сна, а флаг "пора проверить кнопки" выставляется таймером. Но суть это не меняет. Логика примерно та же: - Читаем состояние. - Увеличиваем/уменьшаем переменную (софт-фильтр), если она в нормальных пределах. Если она в ОСОБЫХ значениях - то это нажатие или длительное нажатие (или даже повторы) Псевдокод: Код: if (ButtonFilter[N] == BTN_PRESS_DURATION) { DoPressCallback(N); } else if (ButtonFilter[N] == BTN_LONG_PRESS_DURATION) { DoLongPressCallback(N); } else if (ButtonFilter[N] == BTN_LONG_PRESS_REPEAT_DURATION) { DoPressRepeatCallback(N); ButtonFilter[N] -= BTN_REPEAT_DURATION; } И условия: 0 < BTN_PRESS_DURATION < BTN_LONG_PRESS_DURATION < BTN_LONG_PRESS_REPEAT_DURATION BTN_REPEAT_DURATION > 0 BTN_REPEAT_DURATION > (BTN_LONG_PRESS_REPEAT_DURATION - BTN_LONG_PRESS_DURATION) Например, BTN_PRESS_DURATION = 50мс BTN_LONG_PRESS_DURATION = 500мс BTN_LONG_PRESS_REPEAT_DURATION = 800мс BTN_REPEAT_DURATION = 200мс Таким образом счётчик фильтра кнопки будет считать с нуля (у меня каждую милисекунду просыпается контроллер, ибо SysTickRate = 1kHz), на отметке 50мс после нажатия кнопки (считается, что антидребезг работает и устранил момент искрения контактов) сработает "Нажатие", затем через 450мс отработает "Длительное нажатие" (можно поднять до 1с), ещё через 300 запустятся повторы и счётчик будет сброшен на значение 600мс и продолжёт тикать вверх до 800, генерируя новый "повтор". И так циклически, пока кнопку не отпустят. Естественно, длительности нужно подбирать "под свои потребности" СпойлерКод: uint8_t Buttons_Tmr[3]; void ButtonsRd(void) { // Power if (GPIOA->IDR & GPIO_IDR_5) { if (Buttons_Tmr[0] < BTN_FILTER * 5) { Buttons_Tmr[0]++; if (Buttons_Tmr[0] == BTN_FILTER * 5) { Buttons_Tmr[0]++; OnBtnPress(0); } } } else { if (Buttons_Tmr[0]) { Buttons_Tmr[0]--; } } // Next if (GPIOA->IDR & GPIO_IDR_9) { if (Buttons_Tmr[1] < BTN_FILTER) { Buttons_Tmr[1]++; if (Buttons_Tmr[1] == BTN_FILTER) { Buttons_Tmr[1]++; OnBtnPress(1); } } } else { if (Buttons_Tmr[1]) { Buttons_Tmr[1]--; } } // Mode if (GPIOA->IDR & GPIO_IDR_10) { if (Buttons_Tmr[2] < BTN_FILTER) { Buttons_Tmr[2]++; if (Buttons_Tmr[2] == BTN_FILTER) { Buttons_Tmr[2]++; timer = 0; OnBtnPress(2); } } } else { if (Buttons_Tmr[2]) { Buttons_Tmr[2]--; } } } int main(void) { // Инициализация пропущена, оставлен только основной цикл while(1) { __WFI(); ButtonsRd(); Job(); } } Тут я НЕ использую длительные нажатия и прочие фокусы, но их можно добавить по желанию. А тут - использую, но без повторов: Код: void ButtonFilfer(uint8_t ButtonNumber, uint8_t Direction) { if (Direction) { BtnFilter[ButtonNumber]++; if (BtnFilter[ButtonNumber] == BUTTON_PRESS_DURATION) { // OnPress() OnButtonPress(ButtonNumber); } else if (BtnFilter[ButtonNumber] == BUTTON_LONG_PRESS_DUR) { // On LongPress() OnButtonLongPress(ButtonNumber); } else if (BtnFilter[ButtonNumber] > BUTTON_LONG_PRESS_DUR) { BtnFilter[ButtonNumber] = BUTTON_LONG_PRESS_DUR; } } else { if (BtnFilter[ButtonNumber]) { BtnFilter[ButtonNumber] = 0; OnButtonRelease(ButtonNumber); } else { BtnFilter[ButtonNumber] = 0; OnButtonRelease(ButtonNumber); } } } |
Автор: | jcxz [ Вт ноя 12, 2024 11:39:43 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Потом просто хендлер с прерываниями по спаду и по фронту поднимает и опускает флажки при нажатии кнопок... 1. Зачем сброс флагов - тремя операциями вместо одной?2. Чтение GPIOA->IDR то же самое - зачем 6(!) чтений вместо одного??? ![]() 3. Вместо прерывания EXTI лучше использовать периодическое прерывание. При таком кривом обработчике прерываний иногда будут создаваться ситуации, когда кнопка оказывается залипшей в нажатом состоянии (или будут пропуски нажатий). Из-за того, что читаете GPIOA->IDR много раз вместо одного. Подумайте - что будет, если кнопка изменит состояние между вашими чтениями? PS: Для вставки кода здесь есть соответствующий тэг "Code". (вместо картинок) |
Автор: | aleksey chilov [ Вт ноя 12, 2024 11:40:23 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Обработчик у вас интересный. Пожалуй я его возьму к себе в проект. Только у меня контролер не спит но я могу поместить обработчик в хендлер по таймеру там у меня он на 100Гц настроен думаю этого вполне достаточно будет. |
Автор: | jcxz [ Вт ноя 12, 2024 11:52:54 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Дальше настроил таймер 3 на 100Гц и в прерывании с частотой 100 ГЦ идёт опрос кнопок Зачем тогда EXTI, если уже есть периодическое прерывание?Какой-то бурелом..... ![]() Добавлено after 1 minute 55 seconds: А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет? Автор один и тот же порт, содержащий все кнопки, читает 6 раз! А вы про битовые переменные.... ![]() Он в принципе не понимает что такое "биты". Судя по коду. ![]() |
Автор: | aleksey chilov [ Вт ноя 12, 2024 11:59:40 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Чё вы несёте??? Какие 6 раз??? Там прерывание настроено по фронту и по спаду на каждый пин порта "А" который опрашивается. Порт в нуле флаг поднялся, второе прерывание когда порт в +3,3 когда кнопку бросил флаг сбросился чё не понятно какие 6 раз читайте внимательно что написанно |
Автор: | jcxz [ Вт ноя 12, 2024 12:01:54 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Примерно так: Код: enum {BUT_1, BUT_2, BUT_3, ...}; Также обращаем внимание на volatile.
uint volatile buttons = 0; void Isr() { EXTI->PR = EXTI_PR_PR5 | EXTI_PR_PR6 | EXTI_PR_PR7; uint i = GPIOA->IDR, c = 0; if (!(i & 1 << 7)) c += 1 << BUT_1; if (!(i & 1 << 6)) c += 1 << BUT_2; if (!(i & 1 << 5)) c += 1 << BUT_3; buttons = c; } |
Автор: | aleksey chilov [ Вт ноя 12, 2024 12:02:08 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
EXTI настраивал дамал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше |
Автор: | jcxz [ Вт ноя 12, 2024 12:03:42 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Чё вы несёте??? Какие 6 раз??? "Несёте" это вы.чё не понятно какие 6 раз читайте внимательно что написанно Ясно. Гопник детектед.Дальше в своём говнокоде бултыхайтесь сами. |
Автор: | Martian [ Вт ноя 12, 2024 12:40:54 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
EXTI настраивал думал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше Это метод тыка. Даже если получите рабочий вариант, это не даст опыта и знаний. Надо по науке: изучить язык, изучить контроллер, продумать алгоритм. И вот тогда идти на форум и спрашивать непонятное. Но, скорее всего, с таким вопросом уже не придёте - не будет непонятного, или же быстро разберётесь сами. jcxz привёл код, так что, больше и говорить нечего. |
Автор: | jcxz [ Вт ноя 12, 2024 13:13:19 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
jcxz привёл код, так что, больше и говорить нечего. По уму в той процедуре ещё хорошо бы после:Код: EXTI->PR = EXTI_PR_PR5 | EXTI_PR_PR6 | EXTI_PR_PR7; добавить какую-то синхронизацию перед чтением IDR. Чтобы быть уверенным, что запись в EXTI->PR реально выполнилась к моменту чтения IDR.Например так (обратным чтением): Код: EXTI->PR = EXTI_PR_PR5 | EXTI_PR_PR6 | EXTI_PR_PR7; Потому как EXTI и GPIO - разная периферия, а значит - может находиться на разных сегментах шин МК.uint j = EXTI->PR; uint i = GPIOA->IDR, c = 0; ... Иначе - есть вероятность сбросить событие переключения состояния кнопки до его чтения. Но это уже - не для ТС. Ему - не читать. Иначе - есть опасность поумнеть. ![]() |
Автор: | aleksey chilov [ Вт ноя 12, 2024 13:17:30 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
За код спасибо! Меня и интересовали методы реализации опроса кнопок. Хотел посмотреть кто как делает чтоб не придумывать то что давно придумано. Ну ничего, разберёмся по маленьку... |
Автор: | Adrift [ Вт ноя 12, 2024 13:20:41 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Код: uint i = GPIOA->IDR, c = 0; if (!(i & 1 << 7)) c += 1 << BUT_1; if (!(i & 1 << 6)) c += 1 << BUT_2; if (!(i & 1 << 5)) c += 1 << BUT_3; buttons = c; } Тут напрашивается функция которая будет битики переносить: Код: uint32_t i = GPIOA->IDR;
buttons = moveBit(i, 7, BUT_1) | moveBit(i, 6, BUT_2) | moveBit(i, 5, BUT_3); |
Автор: | jcxz [ Вт ноя 12, 2024 13:22:46 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Тут напрашивается функция которая будет битики переносить: Конечно, так лучше. Но для начинающих может быть уже сложно. Не все они знают - что такое макросы. Код: uint32_t i = GPIOA->IDR; buttons = moveBit(i, 7, BUT_1) | moveBit(i, 6, BUT_2) | moveBit(i, 5, BUT_3); ![]() Ещё лучше описать пины кнопок в хидере: Код: ... PS: Это для тех, кто знает - что такое "макрос". ![]() |
Автор: | Martian [ Вт ноя 12, 2024 13:35:34 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
buttons = GPIOA->IDR & mask; ![]() |
Автор: | Adrift [ Вт ноя 12, 2024 13:43:24 ] |
Заголовок сообщения: | Re: Обработка кнопок, EXTI[0] |
Ещё лучше описать пины кнопок в хидере: Код: ... Пины в хедере - это уже дикий оверхед, придется читать с порта по разу на каждую кнопку ) |
Страница 1 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |