Например TDA7294

Форум РадиоКот • Просмотр темы - 2 кнопки - Нужно выжать 5 режимов обработки.
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вт дек 16, 2025 14:00:22

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 54 ]  1, ,  
Автор Сообщение
Не в сети
 Заголовок сообщения: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Чт фев 10, 2022 22:16:10 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
Всем привет. Нашел тут на просторах Инета интересный пример у
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 KiB]
Скачиваний: 174
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Чт фев 10, 2022 22:58:51 
Потрогал лапой паяльник
Аватар пользователя

Карма: 4
Рейтинг сообщений: 108
Зарегистрирован: Вс окт 25, 2020 22:13:25
Сообщений: 395
Откуда: Смоленск
Рейтинг сообщения: 1
Странный пример какой-то... Вторая кнопка имеет более высокий приоритет... Может конечно так и задумывалось...

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

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

Ну либо если по простому и не жалко памяти, то завести "button_clk_1" и "button_clk_2" и анализировать потом две переменные. Но, как программирующий для AVR на asm, этот подход считаю не верным.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Чт фев 10, 2022 23:30:18 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 256
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2089
Рейтинг сообщения: 1
Есть у меня парочка классов для 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 для длинного нажатия.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Чт фев 10, 2022 23:35:04 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
Приоритет и правда выше. Я этот эфект заметил, когда эесперементировал.
Вот бы вы подробнее объяснили почему и из-за чего.

А ваш пример с битами вообще не понял, если честно.
Не дотягиваю я до этого уровня пока.


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Чт фев 10, 2022 23:54:03 
Потрогал лапой паяльник
Аватар пользователя

Карма: 4
Рейтинг сообщений: 108
Зарегистрирован: Вс окт 25, 2020 22:13:25
Сообщений: 395
Откуда: Смоленск
Рейтинг сообщения: 0
Приоритет т правда выше. Я этот эфект заметил, когда эесперементировал.
Вот бы вы подробнее объяснили почему и из-за чего.

В обработчике прерывания вначале анализируется состояние пина 1-й кнопки. Результат сохраняется в "button_clk".
Затем анализируется пин 2-й кнопки. Результат сохраняется опять же в "button_clk". Соответственно, мы "забыли" что там сохранили по первой кнопке.


Не дотягиваю я до этого уровня пока.

Тогда пробуйте сделать две переменных (button_clk1 и button_clk2), состояние каждой кнопки сохраняйте в свою переменную. Тогда ничего не будет затираться и кнопки будут иметь одинаковый приоритет.

Добавлено after 4 minutes 18 seconds:
Есть у меня парочка классов

Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.
Мы так его совсем запутаем :beer:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 00:01:41 
Собутыльник Кота
Аватар пользователя

Карма: -12
Рейтинг сообщений: -24
Зарегистрирован: Пт июл 12, 2019 22:52:01
Сообщений: 2516
Рейтинг сообщения: 0
Я себе обработчик кнопок через конечный автомат делал. У каждой кнопки есть набор состояний, в суперлупе не чаще раза в миллисекунду запускается проверка состояния кнопок. Если нужно детектировать долгое одновременное нажатие нескольких кнопок, достаточно их состояния сравнить где-нибудь в любом месте программы.

_________________
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 00:03:57 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 256
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2089
Рейтинг сообщения: 0
Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.

ООП я как раз не предлагаю, потому от изначального варианта там мало что осталось, просто функции внутри класса которые без проблем можно использовать отдельно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 00:45:41 
Держит паяльник хвостом
Аватар пользователя

Карма: 2
Рейтинг сообщений: 154
Зарегистрирован: Ср окт 04, 2017 20:47:40
Сообщений: 984
Рейтинг сообщения: 0
Цитата:
ДядяВован
Я хотел топикстартера в сторону ассемблера направить, а Вы ему ООП предлагаете.
Мы так его совсем запутаем :beer:

Тоже поддерживаю данный посыл.
Но начинать новичку всё же Имхо нужно с графа, где расписана только логика процесса (сиречь последовательность событий). Т. е. поэтапно, не всё сразу. А на чём он её потом будет реализовывать (на ассемблере или любом другом языке) уже неважно.
И из практики - такой подход проще осваиваем и многие потом сами на простых задачах запросто переходят на ассемблер.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 08:42:40 
Вымогатель припоя

Карма: -8
Рейтинг сообщений: 49
Зарегистрирован: Вс дек 28, 2014 21:54:05
Сообщений: 615
Рейтинг сообщения: 0
Double click ещё есть ;)

_________________
Я всё-всё узнAю и стану профессором.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:24:58 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
Из примера в топике у меня получилось реализовать только еще более длительное нажатие на кнопку пудем добавления колличества в счетчике и отдельного условия под него.
Но на мой взгляд, как пользователя, это не совсем удобно, поскольку среднее нажатие нужно ловить интуитивно.
Я по удлинненному длинному клику делал быструю смену значений переменной. Что бы 900 секунд по одному клику не накручивать.
Дабл клик, мне кажется тоже не лучшим вариантом, поскольку не исключает возможности случайного двойного нажатия.

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:27:27 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4594
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Vovik-78 писал(а):
да и кнопок всего 3
Всего ?
На 3-х кнопках можно чёрта лысого сделать. Достаточно от них событий короткого и длинного нажатий.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:40:47 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
Короткие, как обычно на обычное управление. Длинные все уже заняты, что бы меню не получалось еще более длинное.
Как раз не хватает нажатия 2х кнопок одновременно. Пока что длнинного нажатияна 2 кнопки. Тогда мне всего хватит. А уж если получится выжать длинное парное, то и короткое парное, думаю будет не проблема.


Последний раз редактировалось Vovik-78 Пт фев 11, 2022 09:50:24, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:48:52 
Вымогатель припоя

Карма: 6
Рейтинг сообщений: 183
Зарегистрирован: Ср янв 06, 2010 10:01:46
Сообщений: 589
Рейтинг сообщения: 0
Мне кажется в корне ущербным, задавать режим разными стилями нажатия кнопок, масштабируемости и логики ноль.
Я делаю двумя кнопками всё что угодно. Одна кнопка - Mode (Step), вторая - Ok (Change)
Пример: Установка времени в часах:
Основной режим (отображение времени) -> Mode (установка десятков часов), кнопка Ok меняет значение
-> Mode (установка единиц часов), кнопка Ok меняет значение -> ... -> Основной режим


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:57:29 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 98
Рейтинг сообщений: 2135
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18446
Откуда: Новочеркасск
Рейтинг сообщения: 1
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
я недавно реализовал, как мне кажется, неплохую систему обработки кнопок... любого количества (до 8 штук, чтобы не морочить голову с большим количеством портов), возможно реагирование на нажатие, на отпускание или на нажатие и удержание нажатой, а так же с автоповтором при удержании, в любых комбинациях нажатий. для корректной работы необходим какой-то независимый счетчик времени (таймер). если интересно, могу рассказать принцип

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Последний раз редактировалось ARV Пт фев 11, 2022 10:01:39, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 09:59:21 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4594
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Vovik-78 писал(а):
Как раз не хватает нажатия 2х кнопок одновременно.
Приведите пример меню (или его отдельного пункта), в котором Вам не хватит 3-х кнопок с обычными нажатиями. Не могу в голове уложить подобное.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 10:10:58 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
В переделываемом устройстве помимо часов есть срабатывание по отсчету импульсов внешнего устройства, срабатывание по времени, 5 различных режимов работы в зависимости от конфигурации и назначения. При этом пересекаются лишь 3 общих режима. В некоторых режимах работы до 14 различных установки. И если на 2х кнопках все это сделать, то для изменения, к примеру, самого дальнего режима в меню, да и если изменить нужно с 500 секунд до 0, для отключения, это сколько же нужно будет стоять и клацать кнопкой.

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

Добавлено after 3 minutes 12 seconds:
Vovik-78 писал(а):
Как раз не хватает нажатия 2х кнопок одновременно.
Приведите пример меню (или его отдельного пункта), в котором Вам не хватит 3-х кнопок с обычными нажатиями. Не могу в голове уложить подобное.

Буду за комппом - скину. Сейчас с мобилька.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 10:13:03 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4594
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Vovik-78 писал(а):
то для изменения, к примеру, самого дальнего режима в меню,
Совсем не понятно, причём тут дальный/ближний/средний режим ? Каким образом, увеличение кол-ва кнопок, или их комбинаций, может уменьшить длину меню (аля, кол-во изменяемых параметров/настроек) ?
PS: 14 пунктов - это вообще ни о чём. 14 раз нажать всего. Есть пром-приборы, в которых по меню можно минут 10 лазить, чтобы куда-то добраться и что-то настроить.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 10:42:00 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
я недавно реализовал, как мне кажется, неплохую систему обработки кнопок... любого количества (до 8 штук, чтобы не морочить голову с большим количеством портов), возможно реагирование на нажатие, на отпускание или на нажатие и удержание нажатой, а так же с автоповтором при удержании, в любых комбинациях нажатий. для корректной работы необходим какой-то независимый счетчик времени (таймер). если интересно, могу рассказать принцип

Один таймер у меня на динамической индикации через сдвиговые регистры. Плюс на третьем сдвигающем слелал подключение/ отключение дополнительного внешнего оборудования (разные насосики и клапаны). Один таймер висит на подсчете импульсов внешнего источника импульсов по Т0 или Т1, не помню.
Один вот, под кнопки.
Внешний источник импульсов можно конечно и на внешнее прерывание завести. Еще один таймер освободив.
Все это на Меге 8а.
Так что да, интересно.
Буду благодарен за любые варианты. Ибо не в этом, так в другом приборе пригодится.

Добавлено after 22 minutes 25 seconds:
Есть пром-приборы, в которых по меню можно минут 10 лазить, чтобы куда-то добраться и что-то настроить.

И что в этом хорошего? :o По мне так проще один раз 2 нажать, чем 20 раз одну. Тем более, что это не невыполнимое желание. Просто я пока не могу его реализовать. для чего и обратился за помощью.
Если бы не размещение в заводском корпусе, который рассчитан на 3 кнопки, то может и добавил бы еще одну или 2.
Но это и для обучающего процесса тоже не правильный подход, на мой взгляд. К такому варианту можно прибегнуть, если совсем нет выхода. А тут есть. просто моих знаний пока не хватает для их реализации. На мой взгляд, устранение пробелов в знании и понимании реализации - самый правильный выход.
Делается это для себя, в первую очередь. И клацать 40 раз мне не очень охота.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 12:34:51 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 98
Рейтинг сообщений: 2135
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18446
Откуда: Новочеркасск
Рейтинг сообщения: 1
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
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, то сначала сработает обработка КОРОТКОГО нажатия, а потом уже ДОЛГОГО.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: 2 кнопки - Нужно выжать 5 режимов обработки.
СообщениеДобавлено: Пт фев 11, 2022 14:30:51 
Встал на лапы

Зарегистрирован: Чт дек 16, 2021 18:20:02
Сообщений: 95
Рейтинг сообщения: 0
код в целом такой


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

Добавлено 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:
Ну либо если по простому и не жалко памяти, то завести "button_clk_1" и "button_clk_2" и анализировать потом две переменные. Но, как программирующий для AVR на asm, этот подход считаю не верным.


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


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 54 ]  1, ,  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y