2 кнопки - Нужно выжать 5 режимов обработки.

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

Всем привет. Нашел тут на просторах Инета интересный пример у
Andrey Frolov "Длинный и короткий клик."
В его примере 2 кнопки. И все мне в этом примере нравится, но вот возникла потребность выжать из него 5ый режим (а в идеале бы и 6-ой), обработку долгого нажатия на обе кнопки сразу.
2ой день голову ломаю - ничего не выходит.
Подскажите как это решить - плиз!

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

#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t button_count;// счетчик кнопки 1
volatile uint8_t button2_count;// счетчик кнопки 2
volatile uint8_t button_clk; // флаг клика

// обработчик прерывания по переполнению таймера 0
ISR(TIMER0_OVF_vect){
	// опрос первой кнопки
	if (PINC&(1<<PC0)) // если на ПИНе 1
	{
		if (button_count>=5 && button_count<60) button_clk=1; //если в рамках поднять флаг короткого клика 1
		button_count=0;// обнулить счетчик
	}
	else  // ИНАЧЕ на ПИНе 0
	{
		if (button_count<61) button_count++; // инкермент счетчика с ограничением 61
		if (button_count==60) button_clk=101;// если в счетчике 60 поднять флаг длинного клика 1
	}
	
	// опрос второй кнопки
	if (PINC&(1<<PC1)) // если на ПИНе 1
	{
		if (button2_count>=5 && button2_count<60) button_clk=2;// если в рамках поднять флаг короткого клика 2
		button2_count=0;// обнулить счетчик
	}
	else  // ИНАЧЕ на ПИНе 0
	{
		if (button2_count<61) button2_count++; // инкермент счетчика с ограничением 61
		if (button2_count==60) button_clk=102; //если в счетчике 60 поднять флаг длинного клика 2
	}
}

int main(void)
{
	TCCR0|=(1<<CS01) | (1<<CS00);// запуск таймера 0 с делителем 64
	TIMSK|=(1<<TOIE0); // разрешить прерывание по переполнению таймера 0
	
	DDRB|=(1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3);// пины светодиодов на выход
	
	sei();//глобально разрешить перерывания
	while (1)
	{
		if (button_clk) // проверка флажка клика
		{
			switch (button_clk)
			{
				case 1:// отработка короткого клика 1
				PORTB^=(1<<PB0);
				break;
				
				case 101:// отработка длинного клика 1
				PORTB^=(1<<PB1);
				break;
				
				case 2:// отработка короткого клика 2
				PORTB^=(1<<PB2);
				break;
				
				case 102:// отработка длинного клика 2
				PORTB^=(1<<PB3);
				break;
			}
			button_clk=0;// сбросить флаг клика в 0
		}
		
	}
}
Вложения
Atmega8_BUTTON2.rar
(90.14 КБ) 185 скачиваний
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 517
Зарегистрирован: Вс окт 25, 2020 22:13:25
Откуда: Смоленск

Сообщение ДядяВован »

Странный пример какой-то... Вторая кнопка имеет более высокий приоритет... Может конечно так и задумывалось...

Я бы вместо вместо числового значения "button_clk" переделал всё на биты.
Например так:
бит 0 = нажата кнопка 1
бит 1 = долго нажата кнопка 1
бит 2 = нажата кнопка 2
бит 3 = долго нажата кнопка 2

В обработчике прерывания выставлять нужные биты. А в "main" соответственно анализировать биты. Таким образом в "button_clk" будет информация о двух кнопках.

Ну либо если по простому и не жалко памяти, то завести "button_clk_1" и "button_clk_2" и анализировать потом две переменные. Но, как программирующий для AVR на asm, этот подход считаю не верным.
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Есть у меня парочка классов для STM32, если более простой упростить и основательно почистить, то останется следующее:
Спойлер

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

class Buttons
{
public:
	struct State
	{
		uint8_t current, longPressed, shortPressed, released;
	};

	void init()
	{
		Port::mode(PinMode::PullUp);
		buttons = {};
		counter = 0;
		prev = prevLongPressed = 0;
		oldTime = 0;
	}

	State state()
	{
		State tmp = buttons;
		buttons.shortPressed = buttons.longPressed = buttons.released = 0;
		return tmp;
	}

	void update()
	{
		uint8_t current = ~Port::read();
		if (current != prev)
		{
			prev = current;
			counter = 0;
			return;
		}

		counter += Delta;

		if (counter >= LongThreshold)
		{
			uint8_t diff = prevLongPressed ^ current;
			buttons.longPressed = diff & current;
			prevLongPressed = current;
			counter = 0;
		}
		else if (counter >= ShortThreshold)
		{
			uint8_t diff = buttons.current ^ current;
			buttons.shortPressed = current & diff;
			buttons.released = buttons.current & diff;
			prevLongPressed &= ~buttons.released;
			buttons.current = current;
		}
	}

private:
	State buttons;
	uint16_t counter;
	uint8_t prev, prevLongPressed;
};
Если Port - это собственно 8-ми битный порт AVR с включенными подтяжками, то данный код может работать с 8-ю кнопками, для каждой будет устанавливаться бит короткого/длинного нажатия и отпускания, помимо текущего состояния. И т.к. счетчик один, то отсчет начнется когда состояние на всех пинах стабилизируется, т.е. нажав две кнопки висящие на двух младших битах получим 0x03 для длинного нажатия.
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

Приоритет и правда выше. Я этот эфект заметил, когда эесперементировал.
Вот бы вы подробнее объяснили почему и из-за чего.

А ваш пример с битами вообще не понял, если честно.
Не дотягиваю я до этого уровня пока.
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 517
Зарегистрирован: Вс окт 25, 2020 22:13:25
Откуда: Смоленск

Сообщение ДядяВован »

[uquote="Vovik-78",url="/forum/viewtopic.php?p=4178658#p4178658"]Приоритет т правда выше. Я этот эфект заметил, когда эесперементировал.
Вот бы вы подробнее объяснили почему и из-за чего.[/uquote]
В обработчике прерывания вначале анализируется состояние пина 1-й кнопки. Результат сохраняется в "button_clk".
Затем анализируется пин 2-й кнопки. Результат сохраняется опять же в "button_clk". Соответственно, мы "забыли" что там сохранили по первой кнопке.


[uquote="Vovik-78",url="/forum/viewtopic.php?p=4178658#p4178658"]Не дотягиваю я до этого уровня пока.[/uquote]
Тогда пробуйте сделать две переменных (button_clk1 и button_clk2), состояние каждой кнопки сохраняйте в свою переменную. Тогда ничего не будет затираться и кнопки будут иметь одинаковый приоритет.

Добавлено after 4 minutes 18 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=4178656#p4178656"]Есть у меня парочка классов[/uquote]
Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.
Мы так его совсем запутаем :beer:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Я себе обработчик кнопок через конечный автомат делал. У каждой кнопки есть набор состояний, в суперлупе не чаще раза в миллисекунду запускается проверка состояния кнопок. Если нужно детектировать долгое одновременное нажатие нескольких кнопок, достаточно их состояния сравнить где-нибудь в любом месте программы.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="ДядяВован",url="/forum/viewtopic.php?p=4178662#p4178662"]Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.[/uquote]
ООП я как раз не предлагаю, потому от изначального варианта там мало что осталось, просто функции внутри класса которые без проблем можно использовать отдельно.
Электрический кот
Аватара пользователя
Сообщения: 1027
Зарегистрирован: Ср окт 04, 2017 20:47:40

Сообщение valentinovich »

ДядяВован
Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.
Мы так его совсем запутаем :beer:
Тоже поддерживаю данный посыл.
Но начинать новичку всё же Имхо нужно с графа, где расписана только логика процесса (сиречь последовательность событий). Т. е. поэтапно, не всё сразу. А на чём он её потом будет реализовывать (на ассемблере или любом другом языке) уже неважно.
И из практики - такой подход проще осваиваем и многие потом сами на простых задачах запросто переходят на ассемблер.
Вымогатель припоя
Сообщения: 615
Зарегистрирован: Вс дек 28, 2014 21:54:05

Сообщение dgrett »

Double click ещё есть ;)
Я всё-всё узнAю и стану профессором.
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

Из примера в топике у меня получилось реализовать только еще более длительное нажатие на кнопку пудем добавления колличества в счетчике и отдельного условия под него.
Но на мой взгляд, как пользователя, это не совсем удобно, поскольку среднее нажатие нужно ловить интуитивно.
Я по удлинненному длинному клику делал быструю смену значений переменной. Что бы 900 секунд по одному клику не накручивать.
Дабл клик, мне кажется тоже не лучшим вариантом, поскольку не исключает возможности случайного двойного нажатия.

Мне понравился приведенный пример тем, что как раз исключена возможность передержки длинного клика.
А быстрый инкремент значения по длинному клику я оставил лишь в некоторых пунктах меню, где нужно будет нащелкать большие значения. В установке часов оставил только короткие нажатия. А установке минут - быстрый инкимент при длинном клике.
Индикация прибора сейчас делается на 8 рязрядном семисерментнике, а меню получается довольно длинное. Установки до 16 параметров в отдельных ветках. Делать возврат к предыдущему пункту - не информативно, да и кнопок всего 3.
Увеличение кол-ва кнопок не вариант. Поскольку планируется установка в заводской корпус прибора просто с увеличением его функционал.

Добавлено after 12 minutes 57 seconds:
Ассемблер конечно хорошо. Я понимаю, что более низкоуровневый язык кодинга - более правильно.
Но я когда то, для свох задач немного сталкивался с Си. По этому он мне сейчас проще для освоения.
Ну и мне кажется, что он более универсален, в смысле разширения горизонтов не только в сторону кодинга контроллеров.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

Vovik-78 писал(а):да и кнопок всего 3
Всего ?
На 3-х кнопках можно чёрта лысого сделать. Достаточно от них событий короткого и длинного нажатий.
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

Короткие, как обычно на обычное управление. Длинные все уже заняты, что бы меню не получалось еще более длинное.
Как раз не хватает нажатия 2х кнопок одновременно. Пока что длнинного нажатияна 2 кнопки. Тогда мне всего хватит. А уж если получится выжать длинное парное, то и короткое парное, думаю будет не проблема.
Последний раз редактировалось Vovik-78 Пт фев 11, 2022 09:50:24, всего редактировалось 1 раз.
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

Мне кажется в корне ущербным, задавать режим разными стилями нажатия кнопок, масштабируемости и логики ноль.
Я делаю двумя кнопками всё что угодно. Одна кнопка - Mode (Step), вторая - Ok (Change)
Пример: Установка времени в часах:
Основной режим (отображение времени) -> Mode (установка десятков часов), кнопка Ok меняет значение
-> Mode (установка единиц часов), кнопка Ok меняет значение -> ... -> Основной режим
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я недавно реализовал, как мне кажется, неплохую систему обработки кнопок... любого количества (до 8 штук, чтобы не морочить голову с большим количеством портов), возможно реагирование на нажатие, на отпускание или на нажатие и удержание нажатой, а так же с автоповтором при удержании, в любых комбинациях нажатий. для корректной работы необходим какой-то независимый счетчик времени (таймер). если интересно, могу рассказать принцип
Последний раз редактировалось ARV Пт фев 11, 2022 10:01:39, всего редактировалось 1 раз.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

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

Vovik-78 писал(а):Как раз не хватает нажатия 2х кнопок одновременно.
Приведите пример меню (или его отдельного пункта), в котором Вам не хватит 3-х кнопок с обычными нажатиями. Не могу в голове уложить подобное.
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

В переделываемом устройстве помимо часов есть срабатывание по отсчету импульсов внешнего устройства, срабатывание по времени, 5 различных режимов работы в зависимости от конфигурации и назначения. При этом пересекаются лишь 3 общих режима. В некоторых режимах работы до 14 различных установки. И если на 2х кнопках все это сделать, то для изменения, к примеру, самого дальнего режима в меню, да и если изменить нужно с 500 секунд до 0, для отключения, это сколько же нужно будет стоять и клацать кнопкой.

Когда доделается на восми семисегментниках, уже буду переделывать на жк 20*4.
Там, по идее, будет проще, в плане информативности пользования.

Добавлено after 3 minutes 12 seconds:
[uquote="Аlex",url="/forum/viewtopic.php?p=4178758#p4178758"]
Vovik-78 писал(а):Как раз не хватает нажатия 2х кнопок одновременно.
Приведите пример меню (или его отдельного пункта), в котором Вам не хватит 3-х кнопок с обычными нажатиями. Не могу в голове уложить подобное.[/uquote]
Буду за комппом - скину. Сейчас с мобилька.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

Vovik-78 писал(а):то для изменения, к примеру, самого дальнего режима в меню,
Совсем не понятно, причём тут дальный/ближний/средний режим ? Каким образом, увеличение кол-ва кнопок, или их комбинаций, может уменьшить длину меню (аля, кол-во изменяемых параметров/настроек) ?
PS: 14 пунктов - это вообще ни о чём. 14 раз нажать всего. Есть пром-приборы, в которых по меню можно минут 10 лазить, чтобы куда-то добраться и что-то настроить.
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

[uquote="ARV",url="/forum/viewtopic.php?p=4178756#p4178756"]я недавно реализовал, как мне кажется, неплохую систему обработки кнопок... любого количества (до 8 штук, чтобы не морочить голову с большим количеством портов), возможно реагирование на нажатие, на отпускание или на нажатие и удержание нажатой, а так же с автоповтором при удержании, в любых комбинациях нажатий. для корректной работы необходим какой-то независимый счетчик времени (таймер). если интересно, могу рассказать принцип[/uquote]
Один таймер у меня на динамической индикации через сдвиговые регистры. Плюс на третьем сдвигающем слелал подключение/ отключение дополнительного внешнего оборудования (разные насосики и клапаны). Один таймер висит на подсчете импульсов внешнего источника импульсов по Т0 или Т1, не помню.
Один вот, под кнопки.
Внешний источник импульсов можно конечно и на внешнее прерывание завести. Еще один таймер освободив.
Все это на Меге 8а.
Так что да, интересно.
Буду благодарен за любые варианты. Ибо не в этом, так в другом приборе пригодится.

Добавлено after 22 minutes 25 seconds:
[uquote="Аlex",url="/forum/viewtopic.php?p=4178764#p4178764"]Есть пром-приборы, в которых по меню можно минут 10 лазить, чтобы куда-то добраться и что-то настроить.[/uquote]
И что в этом хорошего? :o По мне так проще один раз 2 нажать, чем 20 раз одну. Тем более, что это не невыполнимое желание. Просто я пока не могу его реализовать. для чего и обратился за помощью.
Если бы не размещение в заводском корпусе, который рассчитан на 3 кнопки, то может и добавил бы еще одну или 2.
Но это и для обучающего процесса тоже не правильный подход, на мой взгляд. К такому варианту можно прибегнуть, если совсем нет выхода. А тут есть. просто моих знаний пока не хватает для их реализации. На мой взгляд, устранение пробелов в знании и понимании реализации - самый правильный выход.
Делается это для себя, в первую очередь. И клацать 40 раз мне не очень охота.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Vovik-78 писал(а):Один вот, под кнопки
под кнопки отдельного таймера не надо, достаточно в любом уже задействованном добавить один счетчик. этот счетчик должен считать примерно каждые 10 мс, можно от 1 до 20, больше не желательно, чтобы не терять события.

код в целом такой:

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

// эти константы измеряются в тиках счетчика, т.е. если счетчик
// тикает каждые 10 мс, то время долгого удержания будет 3 сек, а врем автоповтора при удержании 300 мс
#define LONG_PRESS_TIME	(300)
#define REPEAT_TIME	(30)
// если ни одна кнопка не нажималась это время, будет послано сообщение EVENT_DEFAULT_MODE
#define DEFAULT_MODE_TIME	(3000)

static event_t prev = EVENT_EMPTY;
static uint16_t cnt;

void reset_event(void){
	cnt = get_ticks();
}

/**
 * функция возвращает код события в момент нажатия кнопки.
 * если кнопка удерживается нажатой долго, то через LONG_PRESS_TIME
 * код события возвращается повторно с флагом EV_LONG,
 * а затем повторяется каждые REPEAT_TIME.
 * при отпускании кнопки код событи не возвращается
 * каждые DEFAULT_MODE_TIME с момента выдачи последнего кода события
 * при отсутствии нажатий кнопок автоматически формируется событие
 * EVENT_DEFAULT_TIME
 * @return код события
 */
event_t get_event(void){
	uint8_t btn = get_key(); // эта функция должна вернуть битовое состояние кнопок
	uint16_t now = get_ticks(); // вот эта функция должна вернуть значение упомянутого счетчика int16_t 

	event_t tmp;

	if(btn == 0){
		// ничего не нажато
		if(!(prev & EV_RELEASED) && (prev != EVENT_EMPTY)){
			// фиксируем момент отпускания
			cnt = now;
			prev |= EV_RELEASED;
			// уточняем, сколько времени прошло с предыдущего нажатия
		} else {
			prev = EVENT_EMPTY;
		}
		if((now - cnt) > DEFAULT_MODE_TIME){
			// если больше заданного - возвращаем событие сброса режима
			cnt = now;
			return EVENT_DEFAULT_MODE;
		}
		return prev;
	} else {
		// что-то нажато, разбираем кнопки по событиям
		// KEY_XXX - это БИТОВЫЕ МАСКИ кнопок
		switch(btn){
		case KEY_UP:	tmp = EVENT_UP; break;
		case KEY_DN:	tmp = EVENT_DN; break;
		case KEY_ENT: 	tmp = EVENT_ENTER; break;
		case KEY_ESC:	tmp = EVENT_ESC; break;
		// а вот и комбинация одновременно нажатых кнопок
		case KEY_UP | KEY_DN:	tmp = EVENT_UPDN; break;
		default:
		// всё, что выше не описано, будет игнорироваться
			tmp = EVENT_EMPTY;
		}
	}
	// проверка долгое/короткое нажатие
	if(tmp == (prev & EVENT_IGNORE_LONG)){
		// нажато то же самое, что и в прошлый раз
		if((now - cnt) > LONG_PRESS_TIME){
			// если время удержания больше заданного, ставим флаг долгого события
			prev = tmp;
			tmp |= EV_LONG;
			cnt += REPEAT_TIME;
			return tmp;
		}
	} else {
		// нажато что-то другое, чем в прошлый раз
		cnt = now; // фиксируем момент нажатия
		prev = tmp; // запоминаем, что нажали
		return tmp;
	}
	return EVENT_EMPTY;
}

/// любое первое событие, кроме пустого и "по умолчанию", сопровождает звуковым сигналом
event_t get_key_event(void){
	event_t ev = get_event();
	//if((ev != EVENT_EMPTY) && (ev != EVENT_DEFAULT_MODE) && !(ev & (EV_RELEASED | EV_LONG)))
	//	play_song(beep);
	return ev;
}

в начале кода есть две функции, которые вы должны реализовать. первая опрашивает порт кнопок и возвращает ЕДИНИЦЫ в битах, соответствующих нажатм кнопкам.
вторая просто должна вернуть значение счетчика тиков.

в дополнение к этому коду вы делаете такое описание комбинаций ваших кнопок

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

/// флаг повтора события (при долгом удержании)
#define EV_LONG		0x80
/// флаг отпускания кнопки
#define EV_RELEASED	0x40

/// варианты генерируемых событий
typedef enum{
	EVENT_EMPTY,						//!< события отсутствуют
	EVENT_UP,							//!< кнопка ВВЕРХ
	EVENT_DN,							//!< кнопка ВНИЗ
	EVENT_ENTER,						//!< кнопка ЭНТЕР
	EVENT_UPDN,							//!< обе кнопки ВВЕРХ и ВНИЗ
	EVENT_ESC,
	EVENT_DEFAULT_MODE,					//!< автособытие - перейти в режим времени
	EVENT_UP_LONG = EVENT_UP | EV_LONG,	//!< ВВЕРХ удерживается долго
	EVENT_DN_LONG = EVENT_DN | EV_LONG,	//!< ВНИЗ удерживается долго
	EVENT_ENTER_LONG = EVENT_ENTER | EV_LONG,//!< ЭНТЕР удерживается долго
	EVENT_UPDN_LONG = EVENT_UPDN | EV_LONG,//!< ВВЕРХ и ВНИЗ удерживаются долго
	EVENT_ENTER_RELEASED = EVENT_ENTER | EV_RELEASED,//!< кнопка ЭНТЕР отпущена
	EVENT_ESC_LONG = EVENT_ESC | EV_LONG,
	EVENT_ESC_RELEASED = EVENT_ESC | EV_RELEASED,
	// не добавлять ниже!
	EVENT_COUNT							//!< общее количество событий (не используется)
} event_t;
в главном коде вы получаете событие и выполняете то, что вам надо сделать

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

event_t ev = get_event();
switch(ev){
case EVENT_NONE: break; // ничего не нажималось и не отпускалось
сase EVENT_UP | EV_RELEASED : break; // если отпущена кнопка UP
case EVENT_UP_LONG: break; // если нажата и долго удерживается кнопка UP
// и так далее
}
единственное, что вы должны учитывать, что если вам надо реагировать раздельно на короткое и долгое нажатие комбинации кнопок, вы должны обрабатывать долгое, как выше, а короткое - НА ОТПУСКАНИЕ, то есть с EV_RELEASED, если сделать без EV_RELEASED просто EVENT_UP, то сначала сработает обработка КОРОТКОГО нажатия, а потом уже ДОЛГОГО.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Сообщения: 95
Зарегистрирован: Чт дек 16, 2021 18:20:02

Сообщение Vovik-78 »

[uquote="ARV",url="/forum/viewtopic.php?p=4178820#p4178820"]код в целом такой[/uquote]

Спасибо вам огромное. Обязательно буду разбираться с вашим примером.

Добавлено after 10 minutes 24 seconds:
А пока что получилось у меня из моего примера выжать Обработчик нажатия двух долгих кнопок.
Код конечно сильно увеличился, и я уверен, что его можно сократить, но в нужном мне формате из всего, что я перепробовал, работает пока что только так.

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

#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t button1_count;// счетчик кнопки 1
volatile uint8_t button2_count;// счетчик кнопки 2
volatile uint8_t button1_clk=0; // клик 1ой кнопки
volatile uint8_t button2_clk=0; // клик 2ой кнопки
volatile uint8_t button3_clk=0;	// клик обеих кнопок
volatile uint8_t button_clk=0; // флаг клика


// обработчик прерывания по переполнению таймера 0
ISR(TIMER0_OVF_vect){
	// опрос первой кнопки
	if (PINC&(1<<PC0)) // если на ПИНе 1
	{
		if (button1_count>=5 && button1_count<60) button1_clk=1; //если в рамках поднять флаг короткого клика 1
		button1_count=0;// обнулить счетчик
	}
	else  // ИНАЧЕ на ПИНе 0
	{
		if (button1_count<61) button1_count++; // инкермент счетчика с ограничением 61
		if (button1_count==60) button1_clk=2;// если в счетчике 60 поднять флаг длинного клика 1
	}
	
	// опрос второй кнопки
	if (PINC&(1<<PC1))  // если на ПИНе 1
	{
		if (button2_count>=5 && button2_count<60) button2_clk=1;// если в рамках поднять флаг короткого клика 2
		button2_count=0;// обнулить счетчик
	}
	else  // ИНАЧЕ на ПИНе 0
	{
		if (button2_count<61) button2_count++; // инкермент счетчика с ограничением 61
		if (button2_count==60) button2_clk=2; //если в счетчике 60 поднять флаг длинного клика 2
	}
	  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	 if ((button1_count>0) && (button2_count>0))
	 {
		if ((button1_count==60) && (button2_count==60))	 //Если кнопки нажаты реально одновременно
		button3_clk=1;
		if ((button1_count==61) && (button2_count==60))	//Если чуть раньше нажата кнопка 1
		button3_clk=1;
		if ((button1_count==60) && (button2_count==61))	 //Если чуть раньше нажата кнопка 2
		button3_clk=1;
		
	 }
	 else 
	 {	
		
		if (button1_clk>0) 
		{
		   if (button1_clk==1)
		   button_clk=1;
		   if (button1_clk==2)
		   button_clk=101;
		} 	
		
		if (button2_clk>0) 
		{
			if (button2_clk==1)
			button_clk=2;
			if (button2_clk==2)
			button_clk=102;
		} 	
	}  
	
	if (button3_clk==1)
	{
		button_clk=111;
	}  
	   button2_clk=0;
	   button1_clk=0;
	   button3_clk=0; 	
}

int main(void)
{
	TCCR0|=(1<<CS01) | (1<<CS00);// запуск таймера 0 с делителем 64
	TIMSK|=(1<<TOIE0); // разрешить прерывание по переполнению таймера 0
	
	DDRB|=(1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4);// пины светодиодов на выход
	
	sei();//глобально разрешить перерывания
	while (1)
	{
		if (button_clk) // проверка флажка клика
		{
			switch (button_clk)
			{
				case 1:// отработка короткого клика 1
				PORTB^=(1<<PB0);
				break;
				
				case 101:// отработка длинного клика 1
				PORTB^=(1<<PB1);
				break;
				
				case 2:// отработка короткого клика 2
				PORTB^=(1<<PB2);
				break;
				
				case 102:// отработка длинного клика 2
				PORTB^=(1<<PB3);
				break;

				case 111:// отработка длинного клика обеих кнопок
				PORTB^=(1<<PB4);
				break;
			}
			button_clk=0;// сбросить флаг клика в 0
		}
		
	}
}

Если кто то подскажет, как сократить код, сохранив функциональность - буду признателен.

Добавлено after 28 minutes 19 seconds:
:))) Хотяяяя, мне наверное даже нравится то, что получилось.
Если убрать обработчик 100% одновременного нажатия двух кнопок - уж сильно маловероятно, и разделить нажатия чуть раньше одной кнопки перед другой , то в моем варианте из 3х кнопок можно получить 12 разных отдельных событий, практически без возможности ложного срабатывания. :)))

Добавлено after 8 minutes 34 seconds:
[uquote="ДядяВован",url="/forum/viewtopic.php?p=4178638#p4178638"]Ну либо если по простому и не жалко памяти, то завести "button_clk_1" и "button_clk_2" и анализировать потом две переменные. Но, как программирующий для AVR на asm, этот подход считаю не верным.[/uquote]

Спасибо Вам за пинок в правильном направлении.
Может то, что получилось, скорее всего не по программному феншую, мне так кажется. Но думаю имеет свое право на жизнь в рамках первого проекта
Ответить

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