Обработка кнопок, EXTI[0]

Кто любит RISC в жизни, заходим, не стесняемся.
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

Добрый вечер кому как.
Подскажите пожалуйста варианты обработки кнопочек, для меню.
Спасибо.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Обработка кнопок, EXTI[0]

Сообщение Аlex »

Покажите свои варианты, а мы оценим :)
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Обработка кнопок, EXTI[0]

Сообщение BOB51 »

Вариантов огромное множество.
Зависит от схемы, компилятора и идеи самого устройства.
8)
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Re: Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

Ну, тут просто флаги и переменные...

Изображение

Добавлено 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 ..
Реклама
Эиком - электронные компоненты и радиодетали
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Обработка кнопок, EXTI[0]

Сообщение Martian »

А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет?
Реклама
Аватара пользователя
AlanDrakes
Прорезались зубы
Сообщения: 236
Зарегистрирован: Пн июл 04, 2016 16:51:22
Откуда: Россия, Омск

Re: Обработка кнопок, EXTI[0]

Сообщение AlanDrakes »

Кто как, а я опрашиваю кнопки в основном потоке, когда код ничего не делает (внутри 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, генерируя новый "повтор".
И так циклически, пока кнопку не отпустят.

Естественно, длительности нужно подбирать "под свои потребности"

Спойлер

Код: Выделить всё

#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);
		}
	}
}
Реклама
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648108#p4648108"]Потом просто хендлер с прерываниями по спаду и по фронту поднимает и опускает флажки при нажатии кнопок...[/uquote]1. Зачем сброс флагов - тремя операциями вместо одной?
2. Чтение GPIOA->IDR то же самое - зачем 6(!) чтений вместо одного??? :shock:
3. Вместо прерывания EXTI лучше использовать периодическое прерывание.

При таком кривом обработчике прерываний иногда будут создаваться ситуации, когда кнопка оказывается залипшей в нажатом состоянии (или будут пропуски нажатий). Из-за того, что читаете GPIOA->IDR много раз вместо одного.
Подумайте - что будет, если кнопка изменит состояние между вашими чтениями?

PS: Для вставки кода здесь есть соответствующий тэг "Code". (вместо картинок)
Последний раз редактировалось jcxz Вт ноя 12, 2024 11:43:16, всего редактировалось 2 раза.
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Re: Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

Обработчик у вас интересный. Пожалуй я его возьму к себе в проект. Только у меня контролер не спит но я могу поместить обработчик в хендлер по таймеру там у меня он на 100Гц настроен думаю этого вполне достаточно будет.
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648108#p4648108"]Дальше настроил таймер 3 на 100Гц и в прерывании с частотой 100 ГЦ идёт опрос кнопок[/uquote]Зачем тогда EXTI, если уже есть периодическое прерывание?
Какой-то бурелом..... :facepalm:

Добавлено after 1 minute 55 seconds:
[uquote="Martian",url="/forum/viewtopic.php?p=4648152#p4648152"]А что, в АРМах теперь для флагов один бит нельзя? И проверки битов больше нет?[/uquote]Автор один и тот же порт, содержащий все кнопки, читает 6 раз! А вы про битовые переменные.... 8)
Он в принципе не понимает что такое "биты". Судя по коду. :dont_know:
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Re: Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

Чё вы несёте??? Какие 6 раз???
Там прерывание настроено по фронту и по спаду на каждый пин порта "А" который опрашивается. Порт в нуле флаг поднялся, второе прерывание когда порт в +3,3 когда кнопку бросил флаг сбросился чё не понятно какие 6 раз читайте внимательно что написанно
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

Примерно так:

Код: Выделить всё

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;
}
Также обращаем внимание на volatile.
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Re: Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

EXTI настраивал дамал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648186#p4648186"]Чё вы несёте??? Какие 6 раз???[/uquote]"Несёте" это вы.

[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648186#p4648186"]чё не понятно какие 6 раз читайте внимательно что написанно[/uquote]Ясно. Гопник детектед.
Дальше в своём говнокоде бултыхайтесь сами.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Обработка кнопок, EXTI[0]

Сообщение Martian »

[uquote="aleksey chilov",url="/forum/viewtopic.php?p=4648190#p4648190"]EXTI настраивал думал флагами как-то кнопки отслеживать но можно и без них я пробовал варианты какие лучше[/uquote]
Это метод тыка. Даже если получите рабочий вариант, это не даст опыта и знаний.
Надо по науке: изучить язык, изучить контроллер, продумать алгоритм. И вот тогда идти на форум и спрашивать непонятное. Но, скорее всего, с таким вопросом уже не придёте - не будет непонятного, или же быстро разберётесь сами.
jcxz привёл код, так что, больше и говорить нечего.
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

[uquote="Martian",url="/forum/viewtopic.php?p=4648215#p4648215"]jcxz привёл код, так что, больше и говорить нечего.[/uquote]По уму в той процедуре ещё хорошо бы после:

Код: Выделить всё

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;
uint j = EXTI->PR;
uint i = GPIOA->IDR, c = 0;
...
Потому как EXTI и GPIO - разная периферия, а значит - может находиться на разных сегментах шин МК.
Иначе - есть вероятность сбросить событие переключения состояния кнопки до его чтения.

Но это уже - не для ТС. Ему - не читать. Иначе - есть опасность поумнеть. 8)
aleksey chilov
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Вс мар 27, 2022 09:38:17

Re: Обработка кнопок, EXTI[0]

Сообщение aleksey chilov »

За код спасибо!
Меня и интересовали методы реализации опроса кнопок.
Хотел посмотреть кто как делает чтоб не придумывать то что давно придумано.
Ну ничего, разберёмся по маленьку...
Последний раз редактировалось aleksey chilov Вт ноя 12, 2024 13:23:59, всего редактировалось 1 раз.
Adrift
Вымогатель припоя
Сообщения: 543
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: Обработка кнопок, EXTI[0]

Сообщение Adrift »

[uquote="jcxz",url="/forum/viewtopic.php?p=4648189#p4648189"]

Код: Выделить всё

  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;
}
[/uquote]
Тут напрашивается функция которая будет битики переносить:

Код: Выделить всё

uint32_t i = GPIOA->IDR;
buttons = moveBit(i, 7, BUT_1) | moveBit(i, 6, BUT_2) | moveBit(i, 5, BUT_3);
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Обработка кнопок, EXTI[0]

Сообщение jcxz »

[uquote="Adrift",url="/forum/viewtopic.php?p=4648233#p4648233"]Тут напрашивается функция которая будет битики переносить:

Код: Выделить всё

uint32_t i = GPIOA->IDR;
buttons = moveBit(i, 7, BUT_1) | moveBit(i, 6, BUT_2) | moveBit(i, 5, BUT_3);
[/uquote]Конечно, так лучше. Но для начинающих может быть уже сложно. Не все они знают - что такое макросы. :wink:

Ещё лучше описать пины кнопок в хидере:

Код: Выделить всё

#define PIN_BUTTON1        A, 7
#define PIN_BUTTON2        A, 6
#define PIN_BUTTON3        A, 5
...
и ссылаться через них, а не через "магические числа".
PS: Это для тех, кто знает - что такое "макрос". :wink:
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Обработка кнопок, EXTI[0]

Сообщение Martian »

buttons = GPIOA->IDR & mask; ;)
Adrift
Вымогатель припоя
Сообщения: 543
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: Обработка кнопок, EXTI[0]

Сообщение Adrift »

[uquote="jcxz",url="/forum/viewtopic.php?p=4648234#p4648234"]Ещё лучше описать пины кнопок в хидере:

Код: Выделить всё

#define PIN_BUTTON1        A, 7
#define PIN_BUTTON2        A, 6
#define PIN_BUTTON3        A, 5
...
[/uquote]
Пины в хедере - это уже дикий оверхед, придется читать с порта по разу на каждую кнопку )
Ответить

Вернуться в «ARM»