Обработка кнопок, EXTI[0]
-
aleksey chilov
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Обработка кнопок, EXTI[0]
Добрый вечер кому как.
Подскажите пожалуйста варианты обработки кнопочек, для меню.
Спасибо.
Подскажите пожалуйста варианты обработки кнопочек, для меню.
Спасибо.
- Реклама
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Обработка кнопок, EXTI[0]
Покажите свои варианты, а мы оценим 
Re: Обработка кнопок, EXTI[0]
Вариантов огромное множество.
Зависит от схемы, компилятора и идеи самого устройства.

Зависит от схемы, компилятора и идеи самого устройства.
-
aleksey chilov
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Re: Обработка кнопок, EXTI[0]
Ну, тут просто флаги и переменные...

Добавлено after 4 minutes 5 seconds:
Потом просто хендлер с прерываниями по спаду и по фронту поднимает и опускает флажки при нажатии кнопок...
Нажата кнопка флаг true отжата false... Булий...

Добавлено after 5 minutes 38 seconds:
Дальше настроил таймер 3 на 100Гц и в прерывании с частотой 100 ГЦ идёт опрос кнопок и обработка ADC и если флаг
кнопки true тогда накапливаем переменную при каждом входе в прерывание если флаг позволяет. Это такакя у меня попытка была создать короткие и долгие нажатия кнопок. Ну и всё... Дальше я завис...

Добавлено after 5 minutes 6 seconds:
Хочу посмотреть другие решения, сколько людей столько и идей... Не хотелось бы прибегать к каким то библиотекам тем более всего 3 кнопки да и библиотеки все на HAL а я использую CMSIS, она меньше памяти хавает правда проблем в 1000.000 раз больше чем в HAL ..
Добавлено after 4 minutes 5 seconds:
Потом просто хендлер с прерываниями по спаду и по фронту поднимает и опускает флажки при нажатии кнопок...
Нажата кнопка флаг true отжата false... Булий...
Добавлено after 5 minutes 38 seconds:
Дальше настроил таймер 3 на 100Гц и в прерывании с частотой 100 ГЦ идёт опрос кнопок и обработка ADC и если флаг
кнопки true тогда накапливаем переменную при каждом входе в прерывание если флаг позволяет. Это такакя у меня попытка была создать короткие и долгие нажатия кнопок. Ну и всё... Дальше я завис...
Добавлено after 5 minutes 6 seconds:
Хочу посмотреть другие решения, сколько людей столько и идей... Не хотелось бы прибегать к каким то библиотекам тем более всего 3 кнопки да и библиотеки все на HAL а я использую CMSIS, она меньше памяти хавает правда проблем в 1000.000 раз больше чем в HAL ..
Re: Обработка кнопок, EXTI[0]
А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет?
- Реклама
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: Обработка кнопок, EXTI[0]
Кто как, а я опрашиваю кнопки в основном потоке, когда код ничего не делает (внутри while (1) { .... __WFI(); } ) обычно после выхода из сна, а флаг "пора проверить кнопки" выставляется таймером.
Но суть это не меняет. Логика примерно та же:
- Читаем состояние.
- Увеличиваем/уменьшаем переменную (софт-фильтр), если она в нормальных пределах. Если она в ОСОБЫХ значениях - то это нажатие или длительное нажатие (или даже повторы)
Псевдокод:
И условия:
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, генерируя новый "повтор".
И так циклически, пока кнопку не отпустят.
Естественно, длительности нужно подбирать "под свои потребности"
Тут я НЕ использую длительные нажатия и прочие фокусы, но их можно добавить по желанию.
А тут - использую, но без повторов:
Но суть это не меняет. Логика примерно та же:
- Читаем состояние.
- Увеличиваем/уменьшаем переменную (софт-фильтр), если она в нормальных пределах. Если она в ОСОБЫХ значениях - то это нажатие или длительное нажатие (или даже повторы)
Псевдокод:
Код: Выделить всё
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, генерируя новый "повтор".
И так циклически, пока кнопку не отпустят.
Естественно, длительности нужно подбирать "под свои потребности"
Спойлер
Код: Выделить всё
#define BTN_FILTER 50
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);
}
}
}
Re: Обработка кнопок, EXTI[0]
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648108#p4648108"]Потом просто хендлер с прерываниями по спаду и по фронту поднимает и опускает флажки при нажатии кнопок...[/uquote]1. Зачем сброс флагов - тремя операциями вместо одной?
2. Чтение GPIOA->IDR то же самое - зачем 6(!) чтений вместо одного???
3. Вместо прерывания EXTI лучше использовать периодическое прерывание.
При таком кривом обработчике прерываний иногда будут создаваться ситуации, когда кнопка оказывается залипшей в нажатом состоянии (или будут пропуски нажатий). Из-за того, что читаете GPIOA->IDR много раз вместо одного.
Подумайте - что будет, если кнопка изменит состояние между вашими чтениями?
PS: Для вставки кода здесь есть соответствующий тэг "Code". (вместо картинок)
2. Чтение GPIOA->IDR то же самое - зачем 6(!) чтений вместо одного???
3. Вместо прерывания EXTI лучше использовать периодическое прерывание.
При таком кривом обработчике прерываний иногда будут создаваться ситуации, когда кнопка оказывается залипшей в нажатом состоянии (или будут пропуски нажатий). Из-за того, что читаете GPIOA->IDR много раз вместо одного.
Подумайте - что будет, если кнопка изменит состояние между вашими чтениями?
PS: Для вставки кода здесь есть соответствующий тэг "Code". (вместо картинок)
Последний раз редактировалось jcxz Вт ноя 12, 2024 11:43:16, всего редактировалось 2 раза.
-
aleksey chilov
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Re: Обработка кнопок, EXTI[0]
Обработчик у вас интересный. Пожалуй я его возьму к себе в проект. Только у меня контролер не спит но я могу поместить обработчик в хендлер по таймеру там у меня он на 100Гц настроен думаю этого вполне достаточно будет.
Re: Обработка кнопок, EXTI[0]
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648108#p4648108"]Дальше настроил таймер 3 на 100Гц и в прерывании с частотой 100 ГЦ идёт опрос кнопок[/uquote]Зачем тогда EXTI, если уже есть периодическое прерывание?
Какой-то бурелом.....
Добавлено after 1 minute 55 seconds:
[uquote="Martian",url="/forum/viewtopic.php?p=4648152#p4648152"]А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет?[/uquote]Автор один и тот же порт, содержащий все кнопки, читает 6 раз! А вы про битовые переменные....
Он в принципе не понимает что такое "биты". Судя по коду.
Какой-то бурелом.....
Добавлено after 1 minute 55 seconds:
[uquote="Martian",url="/forum/viewtopic.php?p=4648152#p4648152"]А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет?[/uquote]Автор один и тот же порт, содержащий все кнопки, читает 6 раз! А вы про битовые переменные....
Он в принципе не понимает что такое "биты". Судя по коду.
-
aleksey chilov
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Re: Обработка кнопок, EXTI[0]
Чё вы несёте??? Какие 6 раз???
Там прерывание настроено по фронту и по спаду на каждый пин порта "А" который опрашивается. Порт в нуле флаг поднялся, второе прерывание когда порт в +3,3 когда кнопку бросил флаг сбросился чё не понятно какие 6 раз читайте внимательно что написанно
Там прерывание настроено по фронту и по спаду на каждый пин порта "А" который опрашивается. Порт в нуле флаг поднялся, второе прерывание когда порт в +3,3 когда кнопку бросил флаг сбросился чё не понятно какие 6 раз читайте внимательно что написанно
Re: Обработка кнопок, EXTI[0]
Примерно так:Также обращаем внимание на volatile.
Код: Выделить всё
enum {BUT_1, BUT_2, BUT_3, ...};
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
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Re: Обработка кнопок, EXTI[0]
EXTI настраивал дамал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше
Re: Обработка кнопок, EXTI[0]
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648186#p4648186"]Чё вы несёте??? Какие 6 раз???[/uquote]"Несёте" это вы.
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648186#p4648186"]чё не понятно какие 6 раз читайте внимательно что написанно[/uquote]Ясно. Гопник детектед.
Дальше в своём говнокоде бултыхайтесь сами.
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648186#p4648186"]чё не понятно какие 6 раз читайте внимательно что написанно[/uquote]Ясно. Гопник детектед.
Дальше в своём говнокоде бултыхайтесь сами.
Re: Обработка кнопок, EXTI[0]
[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648190#p4648190"]EXTI настраивал думал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше[/uquote]
Это метод тыка. Даже если получите рабочий вариант, это не даст опыта и знаний.
Надо по науке: изучить язык, изучить контроллер, продумать алгоритм. И вот тогда идти на форум и спрашивать непонятное. Но, скорее всего, с таким вопросом уже не придёте - не будет непонятного, или же быстро разберётесь сами.
jcxz привёл код, так что, больше и говорить нечего.
Это метод тыка. Даже если получите рабочий вариант, это не даст опыта и знаний.
Надо по науке: изучить язык, изучить контроллер, продумать алгоритм. И вот тогда идти на форум и спрашивать непонятное. Но, скорее всего, с таким вопросом уже не придёте - не будет непонятного, или же быстро разберётесь сами.
jcxz привёл код, так что, больше и говорить нечего.
Re: Обработка кнопок, EXTI[0]
[uquote="Martian",url="/forum/viewtopic.php?p=4648215#p4648215"]jcxz привёл код, так что, больше и говорить нечего.[/uquote]По уму в той процедуре ещё хорошо бы после:
добавить какую-то синхронизацию перед чтением IDR. Чтобы быть уверенным, что запись в EXTI->PR реально выполнилась к моменту чтения IDR.
Например так (обратным чтением):Потому как EXTI и GPIO - разная периферия, а значит - может находиться на разных сегментах шин МК.
Иначе - есть вероятность сбросить событие переключения состояния кнопки до его чтения.
Но это уже - не для ТС. Ему - не читать. Иначе - есть опасность поумнеть.
Код: Выделить всё
EXTI->PR = EXTI_PR_PR5 | EXTI_PR_PR6 | EXTI_PR_PR7;Например так (обратным чтением):
Код: Выделить всё
EXTI->PR = EXTI_PR_PR5 | EXTI_PR_PR6 | EXTI_PR_PR7;
uint j = EXTI->PR;
uint i = GPIOA->IDR, c = 0;
...Иначе - есть вероятность сбросить событие переключения состояния кнопки до его чтения.
Но это уже - не для ТС. Ему - не читать. Иначе - есть опасность поумнеть.
-
aleksey chilov
- Нашел транзистор. Понюхал.
- Сообщения: 167
- Зарегистрирован: Вс мар 27, 2022 09:38:17
Re: Обработка кнопок, EXTI[0]
За код спасибо!
Меня и интересовали методы реализации опроса кнопок.
Хотел посмотреть кто как делает чтоб не придумывать то что давно придумано.
Ну ничего, разберёмся по маленьку...
Меня и интересовали методы реализации опроса кнопок.
Хотел посмотреть кто как делает чтоб не придумывать то что давно придумано.
Ну ничего, разберёмся по маленьку...
Последний раз редактировалось aleksey chilov Вт ноя 12, 2024 13:23:59, всего редактировалось 1 раз.
Re: Обработка кнопок, EXTI[0]
[uquote="jcxz",url="/forum/viewtopic.php?p=4648189#p4648189"][/uquote]
Тут напрашивается функция которая будет битики переносить:
Код: Выделить всё
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);Re: Обработка кнопок, EXTI[0]
[uquote="Adrift",url="/forum/viewtopic.php?p=4648233#p4648233"]Тут напрашивается функция которая будет битики переносить:
[/uquote]Конечно, так лучше. Но для начинающих может быть уже сложно. Не все они знают - что такое макросы. 
Ещё лучше описать пины кнопок в хидере:и ссылаться через них, а не через "магические числа".
PS: Это для тех, кто знает - что такое "макрос".
Код: Выделить всё
uint32_t i = GPIOA->IDR;
buttons = moveBit(i, 7, BUT_1) | moveBit(i, 6, BUT_2) | moveBit(i, 5, BUT_3);Ещё лучше описать пины кнопок в хидере:
Код: Выделить всё
#define PIN_BUTTON1 A, 7
#define PIN_BUTTON2 A, 6
#define PIN_BUTTON3 A, 5
...PS: Это для тех, кто знает - что такое "макрос".
Re: Обработка кнопок, EXTI[0]
buttons = GPIOA->IDR & mask; 
Re: Обработка кнопок, EXTI[0]
[uquote="jcxz",url="/forum/viewtopic.php?p=4648234#p4648234"]Ещё лучше описать пины кнопок в хидере:
[/uquote]
Пины в хедере - это уже дикий оверхед, придется читать с порта по разу на каждую кнопку )
Код: Выделить всё
#define PIN_BUTTON1 A, 7
#define PIN_BUTTON2 A, 6
#define PIN_BUTTON3 A, 5
...Пины в хедере - это уже дикий оверхед, придется читать с порта по разу на каждую кнопку )


