Jump to content
-=FISHER=-

Управление меню с помощью трёх кнопок (Си)

Recommended Posts

Всем здравствуйте!

В моем проекте потребовалось реализовать меню для настройки параметров и управлять им планирую с помощью трёх кнопок. Причем вход в меню и перемещение между пунктами, хотел реализовать длинным нажатием кнопки SET. А регулировку параметров короткими нажатиями на + и -. 

Подскажите пожалуйста какие есть варианты реализации такого меню на Си? Предполагаю, что лучше всего будет сделать через switch, однако в моем проекте в главном цикле уже есть один switch для выбора отображаемой информации (часы, температура, напряжение). В частности происходит путаница в голове где отслеживать нажатия кнопок? Отдельная функция или как-то внутри switch для меню?...

Скрытый текст

MENU.jpg.ab2ba9cfe562cc489c7edc5242a88286.jpg

 


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites
2 часа назад, -=FISHER=- сказал:

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

правильное решение... и что это меняет? в главном цикле по флагу системного тика опрашиваете кнопки , далее кася

часы =0, температура=2, напряжение=3, меню1=4, парам1.1=5, парам1.2=6, меню2=7, парам2.1=8, парам2.2=9 и тд

3 часа назад, -=FISHER=- сказал:

 А регулировку параметров короткими нажатиями на + и -. 

. при малом кол-ве кнопок обычно делается: вход/выход в меню/подменю/параметры Set , циклическое перемещение по пунктам Move,  циклическое изменение параметра Change

Share this post


Link to post
Share on other sites
8 часов назад, IMXO сказал:

при малом кол-ве кнопок обычно делается: вход/выход в меню/подменю/параметры Set , циклическое перемещение по пунктам Move,  циклическое изменение параметра Change

Я делал 3 кнопки так: SELECT - выбор пункта меню (выбор изменяемого параметра), UP и DN - изменение выбранного параметра в соответствующую сторону, подменю не предусматривалось. Длинные нажатия не требуются: после отсутствия нажатий любой кнопки в течение определенного времени режим меню отключается автоматически, и включается обычный режим - индикация того, чего надо. В обычном режиме кнопки UP/DN могут менять какой-то один оперативный параметр, например, яркость индикатора, чтобы по меню не лазить для этой функции, а могут и не работать вообще.

12 часов назад, -=FISHER=- сказал:

какие есть варианты реализации такого меню на Си?

Вариантов много. Например, последнее время я становлюсь сторонником максимального абстрагирования от "кнопок" и т.п. интерфейсов в "главном" коде: от кодов кнопок я уходу в "сообщения" или "события". Главный код содержит обращение к функции, возвращающей полученное событие. Если таковое событие получено, далее оно обрабатывается switch-ем. При этом событие "вход в меню" или "выбор другого пункта меню" отсутствует в принципе, зато есть событие "ПАРАМЕТР_1_БОЛЬШЕ" или "ПАРАМЕТР_3_МЕНЬШЕ".

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

Реализация такого подхода довольно сложная, т.к., как правило, есть одно узкое место - дисплей, который приходится делить между главным кодом и "генератором событий через меню". 

В конечном итоге, автомат состояний позволяет разрешить все проблемы, но почти всегда это приводит к возникновению многовложенных switch-ей в коде...


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites

Новые контролллеры VIPerPLUS - практический вебинар 10 июня от ST

В программе вебинара - новые контроллеры VIPerPlus, расширяющие границы применения этих компонентов. Обзор их характеристик и преимуществ. Практика. Демонстрация испытаний из лаборатории ST. Пример моделирования в среде E-DesignSuite.

Зарегистрироваться

14 часов назад, IMXO сказал:

правильное решение... и что это меняет? в главном цикле по флагу системного тика опрашиваете кнопки , далее кася

часы =0, температура=2, напряжение=3, меню1=4, парам1.1=5, парам1.2=6, меню2=7, парам2.1=8, парам2.2=9 и тд

 В общем случае вот так получается?

Скрытый текст

       switch(mode)
        {
            case MODETIMEVIEW:
            {
  
                break;                
            }

            case MODETEMPVIEW:
            {

                break;
            }
            
            case MODEVOLTVIEW:
            {            

                break;    
            }   
           
            case MODE_MENU1_VIEW:
            {
  
                break;                
            }

            case MODE_PARAM1.1_VIEW:
            {

                break;
            }
            
            case MODE_PARAM1.2_VIEW:
            {            

                break;    
            } 
           
            case MODE_MENU2_VIEW:
            {
  
                break;                
            }

            case MODE_PARAM2.1_VIEW:
            {

                break;
            }
            
            case MODE_PARAM2.2_VIEW:
            {            

                break;    
            } 
        }

 

А опрос всех трех кнопок получается нужно будет вызывать из каждого CASE ? Я к тому что, как сделать чтобы кнопка понимала что в настройках минут, нужно менять только от 0 до 59, в часах от 0 до 23, а предположим в МЕНЮ2.ПАРАМЕТР2 только от 1 до 10.


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites
38 минут назад, -=FISHER=- сказал:

Я к тому что, как сделать чтобы кнопка понимала что в настройках минут, нужно менять только от 0 до 59, в часах от 0 до 23, а предположим в МЕНЮ2.ПАРАМЕТР2 только от 1 до 10.

Я подобную задачу решал несколько иным способом, чем описывал давеча. Но в чем-то сходным.

Я создавал структуру меню, где каждому пункту меню сопоставлялись не только "наименования" пункта, но и указатель на данные, функция изменения этих данных и указатель на "края". Таким образом, при каждом нажатии кнопки в меню вызывалась функция изменения данных, которая получала направление изменения (про коду кнопки), указатель на данные, указатель на границы изменения данных. Эта же функция при необходимости отображала сами данные.

Каждый пункт меню при этом мог иметь собственную функцию редактирования данных, но в общем и целом работа с любым пунктом меню велась одним и тем же способом. Кое-что из этого подхода можно найти в моей "библиотечке" TUI, хотя делал её я очень давно и похвастаться красотой кода я вряд могу... Но принципы, заложенные в основу, я и сейчас успешно применяю. 

Обновления библиотечки: раз, два и три.


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
                     

Технология SOI против паразитных эффектов в драйверах затвора

Микросхемы драйверов затвора силовых транзисторов, изготавливаемые по технологии монолитного кремния, подвержены негативному влиянию отрицательных напряжений, возникающих на опорном выводе для верхнего плеча. Технология «Кремний-на-изоляторе» (Silicon-on-insulator, SOI) является надежным решением этой проблемы, о чем свидетельствуют результаты испытаний трех микросхем драйверов затвора полумостовой схемы, в том числе – SOI-драйвера производства Infineon.

Читать статью

Posted (edited)
1 час назад, -=FISHER=- сказал:

 В общем случае вот так получается?

Я к тому что, как сделать чтобы кнопка понимала что в настройках минут, нужно менять только от 0 до 59, в часах от 0 до 23, а предположим в МЕНЮ2.ПАРАМЕТР2 только от 1 до 10.

Опрос кнопок - это одна функция, возвращающая код "нажатия виртуальной кнопки".

Реакция на "нажатую виртуальную кнопку" - другая  функция.

В функциях реакции выполняется вся нужная валидизация: в функции изменения минут контролируется что бы минут не было больше 59, в функции часов  что бы не более 12/24,  а в функции работы с   Х -сколько нужно для него.

В итоге функционал не привязывается к меню абсолютно. Код прозрачнвй и масштабируемый.

 

Edited by dasZebra

Share this post


Link to post
Share on other sites
1 час назад, dasZebra сказал:

Опрос кнопок - это одна функция, возвращающая код "нажатия виртуальной кнопки".

А почему вы пишите виртуальной кнопки? 

1 час назад, dasZebra сказал:

В итоге функционал не привязывается к меню абсолютно. Код прозрачнвй и масштабируемый

А могли бы представить хотя бы минимальный кусочек кода, чтобы проще было понять алгоритм?


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Я просто думал сделать такой алгоритм изначально: длительное нажатие на кнопку SET открывает первый пункт меню, а также осуществляет переход между пунктами меню, чтобы зайти в выбранный пункт нажимаем на SET коротко. А уже изменение параметров внутри пункта происходит путем нажатия кнопок + и -.

И вот поэтому я не совсем понимаю как обойтись в таком случае без обработки длинных нажатий.


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Вы для какого девайса меню делаете? Перемещение по пунктам долгим нажатием явно неудобно будет для большинства случаев...

Далее: индикатор какой? ЖКИ символьный или 7-сегментный ? 

Я столько вариантов меню делал, что наверняка смогу подсказать удобный в эксплуатации и программировании вариант. Был даже опыт с ОДНОКНОПОЧНЫМ управлением :)


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
Posted (edited)

В прошлом своем "однокнопочном" проекте, правда без меню, я применил вот такую функцию опроса длинного и короткого кнопки. Этот код хорошо работал. Но вот как применить его в этом проекте с меню, ума не приложу. Пока на ум пришла вот такая конструкция. Но что правильнее делать дальше?

Скрытый текст

 


#define PORT_BTN		PORTD
#define DDR_BTN			DDRD
#define PIN_BTN			PIND

#define BIT_PLUS_BTN    _BV(0)
#define BIT_MINUS_BTN   _BV(1)
#define BIT_SET_BTN     _BV(2) 

void Read_Button_State(unsigned char b) //функция опроса кнопки
{
	if(!(PIN_BTN&b)) //проверяем нажатие кнопки
	{
		if(but_count<10){but_count++;} //считаем время антидребезга ~10 мс
		else
		{
			if(but_long_press<500){but_long_press++;} //считаем время длительного нажатия ~0.5 с
			else
			{
				//делаем то, что хотели после длительного нажатия
				but_trig=1; //устанавливаем флаг длительного нажатия
			}
		}
	}
	else
	{
		if((but_long_press>0)&&(but_trig==0)) //если нажатие было, и оно НЕ было длинным, то
		{
			//делаем то, что хотели после короткого нажатия
		}
		if(but_trig){but_trig=0;} //если до этого было длинное нажатие, сбрасываем его флаг
		but_long_press=0; //сбрасываем счетчик длительного нажатия
	}	
}  
  
  
ISR (TIMER0_OVF_vect) //в прерывании по переполнению, примерно 1 раз в 1 мс
{
	Read_Button_State(BIT_SET_BTN); //опрашиваем кнопку SET
	Read_Button_State(BIT_MINUS_BTN ); //опрашиваем кнопку "-"
	Read_Button_State(BIT_MINUS_BTN ); //опрашиваем кнопку "+"
}

 

 

5 минут назад, ARV сказал:

Вы для какого девайса меню делаете? Перемещение по пунктам долгим нажатием явно неудобно будет для большинства случаев...

Далее: индикатор какой? ЖКИ символьный или 7-сегментный ? 

1. Часы, термометр, вольтметр;

2. 7-сегментный индикатор.

 

P.S. понятное дело, что в моем варианте, у каждой кнопки должны быть свои переменные:

but_count, but_long_press, but_trig

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Для часов с 7-сегментным индикатором меню, как таковое, не требуется: мигание разрядов будет информировать о том или ином режиме настроек. Если часы не наручные, то долгих нажатий не надо: первое нажатие SET включает мигание часов, второе минут, третье секунд, затем либо переход к календарю, либо выключение мигания. 

Автомат состояний определяет диапазон изменения настраиваемого значения. При переходе между состояниями эти границы меняются. Все очень просто...

Что настраивать в вольтметре и термометре, я не знаю.


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
Posted (edited)
12 минут назад, ARV сказал:

Что настраивать в вольтметре и термометре, я не знаю.

1.       Настройка времени:

           1.1.    Настройка минут (моргают минуты);

           1.2.    Настройка часов (моргают часы).

2.       Настройка яркости:

          2.1.    Дневная яркость;

          2.2.    Ночная яркость.

3.       Оповещения:

          3.1.    Температура за бортом ниже -4;

          3.2.    Возможно, ещё что-то добавлю.

4.       Анимация включения:

          4.1.    Вариант 1;

          4.2.    ***;

          4.3.    Вариант n.

5.       Анимация смены отображения (Часы <=> t в салоне <=> t за бортом <=> Вольтметр)

         5.1.    Вариант 1;

         5.2.    ***;

         5.3.    Вариант n.

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

А вы себе чётко представляете, как именно это многообразие вариантов будет показано на 7-сегментах?!

То есть как отличать один пункт от другого?


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
8 минут назад, ARV сказал:

А вы себе чётко представляете, как именно это многообразие вариантов будет показано на 7-сегментах?!

Я уверен что что-нибудь придумаю, а тем кто (если ВДРУГ) захотят повторить, обязательно напишу подробную инструкцию по настройке.

Вот кстати как я себе представляю навигацию по меню:

Скрытый текст

1371828905_.JPG.4d379e2849a8f3382565668535bf6616.JPG

 


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites
Posted (edited)

Логика понятна. Но сам смысл меню в унификации, т.е. действия должны быть однотипными для разных пунктов, как и индикация тоже. Если настройка часов обозначается миганием редактируемого разряда, то как аналогичным образом "замигать" остальное, я не представляю. Имхо, начать надо с этого.

А после продумывания того, как ОДНОТИПНО отображать и редактировать разное, станет понятно, какими функциями это реализовывать. Имхо...

Edited by ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
Posted (edited)
18 минут назад, ARV сказал:

А после продумывания того, как ОДНОТИПНО отображать и редактировать разное, станет понятно, какими функциями это реализовывать. Имхо...

Я думаю например вот так:

Скрытый текст

1687426858_.JPG.70cabb4316623dfeb46a44a26e15cbc8.JPG

И кстати, чтобы зайти в меню из любого режима отображения (Часы - термометр - вольтметр), тоже зажимаем долго кнопку SET

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites
4 часа назад, -=FISHER=- сказал:

А почему вы пишите виртуальной кнопки? 

Изделие имеет всего например 3 физические кнопки. По сути ваша задача эмулировать этими тремя кнопками необходимое количество кнопок - виртуальных кнопок. Ну например:

Минуты+; Минуты-; Часы+; Часы-; .... PараметряN+; PараметрN-.

4 часа назад, -=FISHER=- сказал:

А могли бы представить хотя бы минимальный кусочек кода, чтобы проще было понять алгоритм?

Код вы сами  прекрасно напишите. А парпдигму я поясню.

1. У вас три физические кнопки. Значит прежде всего вам нужно детектировать их нажатие.  Пишите функцию GetRealButton(), которая слушает ноги и возвращает (присваивает глобальной переменной) код нажатой кнопки. Эта функцию вы  вызывете  в главном цикле с заданным вами интервалом. То есть если была нажата кнопка 1 то переменная chRealButtonMem будет равна 1. Если нажата кнопка 2 то 2, если было длительное нажатие кнопки 3 то 46, а если кнопки 1 и 2 были нажаты одновременно то код 69.

2. Теперь нужно развернуть логику вложенности.   В главном цикле вызывается фунция GetMenu(), слушающая переменную chRealButtonMem и в зависимости от её значения, текущего состояния и логики изделия присваивающая переменной chVirtualButtonMem  нужный код.  

3. Теперь обработка децствиц меню. В главном цикле вызываются нужные обработчики, слушающие переменную chVirtualButtonMem, и при обнаружении что эта переменная равна определенному значению, выполняющие нужное действие.

do while(1)

 {

 chRealButtonMem=GetRealButton(); //слушаем ноги

chVirtualButtonMem=GetMenu(chRealButtonMem); //слушаются три реальные кнопки без дребезга но с блэкджеком и шлюхами

Обработчик1(chVirtualButtonMem); // выполняется запрошенное действие

Обработчик2(chVirtualButtonMem); //выполняется запрошенное действие

....

DisplayShow1(chVirtualButtonMem); // отображается нужное на дисплее

DisplayShow2(chVirtualButtonMem); //отображается нужное на дисплее

....

chRealButtonMem=0; // нажатие отработанно

chVirtualButtonMem=0; // запрошенное действие отработанно

ОстальныеДействия();

}

 

В итоге у вас  разделены физический уровень, логический уровень и уровень  функционирования устройства.

 

Share this post


Link to post
Share on other sites
7 часов назад, dasZebra сказал:

chVirtualButtonMem=GetMenu(chRealButtonMem); //слушаются три реальные кнопки без дребезга но с блэкджеком и шлюхами

Но, почему без обработки дребезга?


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Потому что там работа ведется уже не с физическими дребезжащими кнопками. а с их кодами, полученными ранее


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
4 минуты назад, ARV сказал:

а с их кодами, полученными ранее

Значит антидребезг обрабатываем при получении кода? А та функция, которую я выше показал, может быть успешно применена для чтения физической кнопки?


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Классический подход заключается в том, что создается "структура меню", в которой существует "пункт меню" и "действие пункта". Пункт меню - это визуально его название, а алгоритмически - это указатель на структуру, в которой, кроме самого названия, есть ссылка либо на действие этого пункта, либо на другую структуру меню - для вложенного меню.

Действие пункта - это то, что выполняется при активации какой-то кнопки, в вашем случае SET.

Главная проблема в том, что потоки команд разделяются на 2 варианта: для "основного режима" и для "хождения по меню". В каждом из потоков приходится делать отдельную функцию вывода на индикатор, отдельную реакцию на кнопки и т.п. Это, конечно, портит стройность алгоритма...

Я избегал подобного раздвоения, загоняя "основной режим" в само меню первым пунктом. Но и тут не все гладко, т.к. в основном режиме индикатор должен обновляться не по командам пользователя, а по внутренним сигналам программы... Снова стройный алгоритм искривляется.

Если не гнаться за этой стройностью, то самый тривиальный switch с кучей case, под которыми тоже switch с кучей case, под которыми... ну вы поняли :) 


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites

вообще для такой простой задачи меню не нужно в полноценном понимании этого слова.

я бы назвал это списком.

и я бы предложил такой список:

1. Часы.      SET -> (мигают минуты - установка минут кнопками "+/-") -> SET -> (мигают часы - установка часов кнопками "+/-")  -> SET -> (закончили установку времени - убрали мигание).

                     также нажатие кнопки SET выводит из настройки времени досрочно после установки минут.

2. t в салоне.      SET не воспринимается.

3.  t за бортом.      SET не воспринимается.

4. Вольтметр.      SET не воспринимается.

5. Яркость.      SET -> (мигает значение яркости - установка яркости кнопками "+/-")  -> SET -> (закончили установку яркости - убрали мигание).

6. Анимация включения.     SET -> (мигает значение анимации - выбор анимации кнопками "+/-")  -> SET -> (закончили выбор анимации - убрали мигание).

7. Оповещения.     SET -> (переходим к перелистыванию оповещений кнопками "+/-")  -> SET -> (закончили перелистывание оповещений).

 

навигация по этому списку производится кнопками "+/-" - вперед/назад, по кольцу, с последнего пункта на первый или с первого на последний.

длинное нажатие кнопки SET тоже не потребуется.


Мудрость приходит вместе с импотенцией...

Share this post


Link to post
Share on other sites
4 часа назад, ARV сказал:

Если не гнаться за этой стройностью, то самый тривиальный switch с кучей case, под которыми тоже switch с кучей case, под которыми... ну вы поняли :) 

В целом понял, но всё же меня интересует, вот эта функция имеет право на жизнь или есть более красивый способ отлавливания коротких и длинных нажатий?

Скрытый текст

void Read_Button_State(unsigned char b) //функция опроса кнопки
{
	if(!(PIN_BTN&b)) //проверяем нажатие кнопки
	{
		if(but_count<10){but_count++;} //считаем время антидребезга ~10 мс
		else
		{
			if(but_long_press<500){but_long_press++;} //считаем время длительного нажатия ~0.5 с
			else
			{
				//делаем то, что хотели после длительного нажатия
				but_trig=1; //устанавливаем флаг длительного нажатия
			}
		}
	}
	else
	{
		if((but_long_press>0)&&(but_trig==0)) //если нажатие было, и оно НЕ было длинным, то
		{
			//делаем то, что хотели после короткого нажатия
		}
		if(but_trig){but_trig=0;} //если до этого было длинное нажатие, сбрасываем его флаг
		but_long_press=0; //сбрасываем счетчик длительного нажатия
	}	
}  

 

 


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites
Только что, -=FISHER=- сказал:

эта функция имеет право на жизнь или

Вы же знаете мой принцип: имеет право на жизнь всё, что приводит к нужному результату :)

Вопрос красоты и алгоритмической полноты - это уже не из области необходимого, а из области перфекционизма. Ваша функция подразумевает, что она будет вызвана трижды для трех кнопок (если все должны отслеживать долгое нажатие). Это явно не логично. Имхо (подчеркиваю, но не навязываю), правильнее было бы оперировать "комбинацией нажатых кнопок", ведь вполне возможна ситуация, когда тот или иной режим должен активироваться одновременным нажатием более одной кнопки.

Второй вопрос, это поведение самого устройства. Возможно 2 принципиальных варианта: реагирование на нажатие и реагирование на отпускание. При реагировании на отпускание проще отличать долгое нажатие от короткого, но это не всегда удобно с точки зрения интерфейса пользователя. Реагирование на нажатие более сложно в реализации, но более "привычно" для потребителя. 

Ваша функция называется "считать состояние кнопки", но внутри себя содержит участки "делать при долгом или кратком нажатии" - это не правильно с точки зрения алгоритма: внутри функции не должно выполняться никакой работы, кроме выяснения состояния кнопок, которое и должно быть возвращено.

Я всегда делаю так.

Создаю функцию get_pressed_keys(void), которая возвращает код, соответствующий всем возможным комбинациям нажатых кнопок. 0 - ничего не нажато, 1 - нажата одна кнопка и т.д. Конечно, каждой комбинации я присваиваю символьный идентификатор.

Затем я создаю функцию get_command(int), которая получает в качестве параметра код комбинации и возвращает уже команду, которая должна быть исполнена. Вот именно в этой функции я отделяю долгие нажатия от коротких, разрешенные комбинации от запрещенных и т.д. Функция вернет CMD_NONE, если на вход поступило что-то не то, иначе вернет конкретную команду, например, CMD_SET_SHORT или CMD_SET_LONG. Главное, постараться отойти от кнопок в сторону абстрактных команд. Это разумно сделать именно с точки зрения перфекционизма и перспективы: наличие абстрактных команд позволит легко и просто внедрить в девайс дистанционное управление любым способом, ведь для программы не будет никакой разницы, как появилась команда - с клавиатуры, из USART или с IR-датчика.

Ну а далее уже дело техники.


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites
Posted (edited)
4 часа назад, ARV сказал:

Ваша функция подразумевает, что она будет вызвана трижды для трех кнопок (если все должны отслеживать долгое нажатие). Это явно не логично. Имхо (подчеркиваю, но не навязываю), правильнее было бы оперировать "комбинацией нажатых кнопок", ведь вполне возможна ситуация, когда тот или иной режим должен активироваться одновременным нажатием более одной кнопки.

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

#define LEFT_IN _BV(PB0) //(1<<PB0)
#define COM _BV(PB1) //(1<<PB1)
#define RIGHT_IN _BV(PB2) //(1<<PB2)
#define SET_BTN _BV(PB3) //(1<<PB3) кнопка настройки
#define ANY_K (RIGHT_IN|COM|LEFT_IN|SET_BTN) //маска для комбинации входных сигналов
  
#define command_Setup_Pause 0x7
#define command_Setup_StandBy 0x5
#define command_Setup_Left 0x4
#define command_Setup_Right 0x1
#define command_Setup_All 0x0

#define ERROR 10

uint8_t get_button(void)
{
	return PINB & ANY_K;
}

uint8_t get_code(void) //опрос портов
{
	code=get_button();
	_delay_ms(3);
	if(code!=get_button()){code=ERROR;}
	return code;
}

//*****************************************

command=get_code();

но я совсем не могу придумать, как при таком подходе мне отловить длительно нажатие?

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...