40-50 мс - нормальное время для принятия решения об уровне сигнала с ручного механического контакта.
Опрос кнопок микроконтроллером
Re: Помогите опросить кнопку
Дребезг нормироваться не может....
...также он зависит от кол-ва выпитого перед нажатием...)))
40-50 мс - нормальное время для принятия решения об уровне сигнала с ручного механического контакта.
40-50 мс - нормальное время для принятия решения об уровне сигнала с ручного механического контакта.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Герконы вообще отличные контакты в плане дребезга, он у них меньше всего. А так у кнопок дребезг сильно зависит от силы нажатия, упругости материала контакта и его чистоты. Для нормальных кнопок дребезг порядка 10мс, у герконов 1-3мс. Герконы более долговечны, поскольку контакты находятся в инертной среде - не окисляются и не подгорают(ибо нечем там, только плавиться).
Re: Помогите опросить кнопку
Alexeyslav писал(а):Если кто найдет более удобную программу для рисования блок-схем, сообщите.
Я рисую в EDGE Diagrammer очень доволен. Еще работал в Diagram Designer
Processor not found! Software emulation ...
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Одна какая-то левая китайская, а другая триальная. Нет счастья в жизни.
Re: Помогите опросить кнопку
Прочитав эту ветку и взяв за основу библиотеку buttons.c решил написать свой опрос кнопок, т.е. изобрести очередной велик 
Получился такой вот код (см. вложение)
Код отслеживает нажатие трех кнопок (можно без проблем увеличить количество), короткое, длинное нажатие и автоповтор каждой из кнопок.
Программа состоит из двух частей:
1. По отпусканию кнопки определяется была ли она нажата и было ли короткое или длинное нажатие.
2. Если кнопка нажата и ей разрешен автоповтор, то выдерживается время до начала автоповтора и выполняется собственно автоповтор.
Планировалась такая структура программы:
т.е. в зависимости от текущего режима мы уходим в соответствующую функцию (подпрограмму)
Вот пример одной из подпрограмм:
И все бы хорошо, но есть проблема!
Если сработала, к примеру, кнопка KEY_UP - происходит смена режима. Соответственно при следующем цикле произойдет переход в соответствующую функцию. Так вот, если в этой функции также используется кнопка KEY_UP, то сразу же происходит выполнение соответствующего кода.
Например, долгое нажатие на KEY_UP переходим в режим установки и сразу же начинается увеличение показаний счетчика.
Как сделать чтобы при одном нажатии мы входили в режим установки, а смена показаний была только при следующем нажатии, а не сразу как сейчас? Может кто решал подобную задачу?
Получился такой вот код (см. вложение)
Код отслеживает нажатие трех кнопок (можно без проблем увеличить количество), короткое, длинное нажатие и автоповтор каждой из кнопок.
Программа состоит из двух частей:
1. По отпусканию кнопки определяется была ли она нажата и было ли короткое или длинное нажатие.
2. Если кнопка нажата и ей разрешен автоповтор, то выдерживается время до начала автоповтора и выполняется собственно автоповтор.
Планировалась такая структура программы:
Код: Выделить всё
// Timer1 overflow interrupt service routine
ISR(TIMER1_OVF_vect)
if(ticTimer == 1) { // таймер тиков для определения временных интервалов короткого, длинного нажатий и автоповтора
cntTic++;
}
}
. . .
main() {
_delay_ms(500);
startup(); // Controller configuration
// Global enable interrupts
sei();
BUT_Init();
while(1) {
FPowerCheck();
switch(Mode) {
case M_SETUP: FSetUp(); break;
case M_VIEWUP: FViewUp(); break;
case M_VIEWDN: FViewDn(); break;
case M_NORMAL: FNormal(); break;
}
}
}т.е. в зависимости от текущего режима мы уходим в соответствующую функцию (подпрограмму)
Вот пример одной из подпрограмм:
Код: Выделить всё
/************************************************ FViewDn */
void FViewDn(void){
// что-то выполняется
Button(); // вызываем опрос кнопок
if( isKey == 1 ) { // флаг что было нажатие
if( (keyPress == KEY_UP) || (keyPress == KEY_ENTER) )
Mode = LastMode; // меняем текущий режим
_resBut(); // обнуляем кнопку
}
}
И все бы хорошо, но есть проблема!
Если сработала, к примеру, кнопка KEY_UP - происходит смена режима. Соответственно при следующем цикле произойдет переход в соответствующую функцию. Так вот, если в этой функции также используется кнопка KEY_UP, то сразу же происходит выполнение соответствующего кода.
Например, долгое нажатие на KEY_UP переходим в режим установки и сразу же начинается увеличение показаний счетчика.
Как сделать чтобы при одном нажатии мы входили в режим установки, а смена показаний была только при следующем нажатии, а не сразу как сейчас? Может кто решал подобную задачу?
- Вложения
-
- Keys_v1.c
- (5.76 КБ) 329 скачиваний
Последний раз редактировалось skeef Ср фев 18, 2015 00:44:31, всего редактировалось 1 раз.
Processor not found! Software emulation ...
Re: Помогите опросить кнопку
Alexeyslav писал(а):Одна какая-то левая китайская, а другая триальная. Нет счастья в жизни.
Могу EDGE скинуть с ключом
Processor not found! Software emulation ...
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Было бы неплохо.
Re: Помогите опросить кнопку
Processor not found! Software emulation ...
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Помогите опросить кнопку
skeef писал(а):1. По отпусканию кнопки определяется была ли она нажата и было ли короткое или длинное нажатие.
...
Например, долгое нажатие на KEY_UP переходим в режим установки и сразу же начинается увеличение показаний счетчика.
Как сделать чтобы при одном нажатии мы входили в режим установки, а смена показаний была только при следующем нажатии, а не сразу как сейчас? Может кто решал подобную задачу?
Заведи еще одну переменную или флаг, лучше переменную, которая увеличивается с каждым приходом длинного нажатия. При отпускании кнопки смотри если она ноль, значит коротко нажали, а если она не ноль, значит было длинное нажатие и нужно сбросить кнопку.
- fox15
- Первый раз сказал Мяу!
- Сообщения: 28
- Зарегистрирован: Вс май 24, 2009 22:25:36
- Откуда: Russia
- Контактная информация:
Re: Помогите опросить кнопку
Вот, как и обещал.
Выкусил из своего проекта все лишнее, оставил только то, что надо.
Проект заточен под Tiny13A
Выполнен на Atmel Studio 6.1 (она официально бесплатна)
FUSE: частота 9.6MHz включен SKDIV8
при использовании другого контроллера или частоты, нужно пересчитать константу задержки (_StabKnob в файле defs.inc)
в зависимости от частоты и делителя таймера
В соответствии с требованиями к проекту, срабатывание кнопки осуществляется по отжатии (как у мышки в Виндовс).
Нажали-отжали кнопку - светодиод загорелся, Нажали-отжали кнопку - светодиод потух
Стратегия проекта предусматривает событийный механизм с подтверждением отработки события в основном цикле.
При желании и в зависимости от частных случаев данную стратегию можно изменить.
Основная суть заключается в том, что срабатывание осуществляется по отжатию и последующему измерению безопасного интервала.
Данный алгоритм рабочий и используется, протестирован с использованием анализатора.
Размер всего кода (FLASH) 156 байт
Выкусил из своего проекта все лишнее, оставил только то, что надо.
Проект заточен под Tiny13A
Выполнен на Atmel Studio 6.1 (она официально бесплатна)
FUSE: частота 9.6MHz включен SKDIV8
при использовании другого контроллера или частоты, нужно пересчитать константу задержки (_StabKnob в файле defs.inc)
в зависимости от частоты и делителя таймера
В соответствии с требованиями к проекту, срабатывание кнопки осуществляется по отжатии (как у мышки в Виндовс).
Нажали-отжали кнопку - светодиод загорелся, Нажали-отжали кнопку - светодиод потух
Стратегия проекта предусматривает событийный механизм с подтверждением отработки события в основном цикле.
При желании и в зависимости от частных случаев данную стратегию можно изменить.
Основная суть заключается в том, что срабатывание осуществляется по отжатию и последующему измерению безопасного интервала.
Данный алгоритм рабочий и используется, протестирован с использованием анализатора.
Размер всего кода (FLASH) 156 байт
- Вложения
-
- Switch.rar
- Обработка кнопки
- (8.61 КБ) 334 скачивания
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Чем это лучше фиксации состояния кнопки по таймеру каждые 10мс?
- fox15
- Первый раз сказал Мяу!
- Сообщения: 28
- Зарегистрирован: Вс май 24, 2009 22:25:36
- Откуда: Russia
- Контактная информация:
Re: Помогите опросить кнопку
Alexeyslav писал(а):Чем это лучше фиксации состояния кнопки по таймеру каждые 10мс?
А это смотря с какой стороны посмотреть.
Допустим мы обрабатываем в одном месте не только кнопку, но и контакты валкодера,
которые требуют немного иного алгоритма и времени и еще много чего и все это сильно увязано.
В любом случае с моей точки зрения, событийный механизм имеет неоспоримые преимущества в сложных системах.
Давайте представим, что мы обрабатываем не только кнопки, но и LCD 2x16 буфер для которого сканируем
15 раз в секунду и 4 канала ADC с MAV фильтром, также у нас USB соединение с компьютером, который может управлять всем процессом, плюс расчет двух каналов с использованием ПИД алгоритма и все эти прелести в реальном времени. И еще валкодер будем накручивать!
Ну и где тут будет фиксация по таймеру каждые 10 ms? В сложной программе мы рискуем "потерять" нажатие на кнопку, а событие не потеряешь! Даже если два события придут одновременно контроллер все равно обработает и второе тоже и ничего не потеряем.
А что лучше или хуже это дело сугубо индивидуальное и зависит от постановки задачи.
Кому-то лучше поставить SN74AHCT14D и забыть про дребезг, а кому-то и SN74AHCT14D не поможет.
Это часть прошлого проекта, все не относящееся к одной кнопке убрано и обработчик сильно упрощен.
А еще можно использовать MikroC, там есть готовые функции с соответствующими входными параметрами

- КРАМ
- Друг Кота
- Сообщения: 25124
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Помогите опросить кнопку
fox15 писал(а):Ну и где тут будет фиксация по таймеру каждые 10 ms? В сложной программе мы рискуем "потерять" нажатие на кнопку, а событие не потеряешь!
Как можно потерять событие, происходящее реже, чем опрос этого события?
В сложной системе достаточно применить один из таймеров как системный и все подобные вещи повесить в обработчике прерываний по этому таймеру. Причем таймер может иметь интервал пересчета (прерываний) соответствующий самым быстрым событиям (например 0,5 мс), а медленные будут обрабатываться через делитель в обработчике (например каждое 16 прерывание или даже реже).
И вообще нужно стараться писать код подобный структуре ОСРВ. С прозрачным разделением ресурсов между задачами.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Так ведь да, 10мс дает тот же таймер по прерыванию и никак его не пропустить. Кнопке вообще безразлично когда её будут проверять, единственное условие - не чаще чем длится потенциальный дребезг который надо подавить. Преимущества - отсутствие сложного алгоритма подавления дребезга, просто считал и все. Сравнил с предыдущим значением и получил такие события как "нажатие" и "отпускание".
С энкодером дело конечно сложнее...
С энкодером дело конечно сложнее...
- КРАМ
- Друг Кота
- Сообщения: 25124
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Помогите опросить кнопку
Alexeyslav писал(а):С энкодером дело конечно сложнее...
На самом деле там нет ничего сложного. Две кнопки с квадратурной диаграммой переключений. Обе защищаются от дребезга как обычные кнопки, причем есть алгоритмы, которые сами по себе бездребезговые, поскольку интервал обработки как раз дает защиту от дребезга.
Я довольно часто ставлю механические энкодеры с осевой кнопкой в разные устройства и всегда и кнопка и энкодер висят на прерывании от системного таймера, совершенно не напрягая общий алгоритм устройства.
- fox15
- Первый раз сказал Мяу!
- Сообщения: 28
- Зарегистрирован: Вс май 24, 2009 22:25:36
- Откуда: Russia
- Контактная информация:
Re: Помогите опросить кнопку
КРАМ писал(а):Alexeyslav писал(а):С энкодером дело конечно сложнее...
На самом деле там нет ничего сложного. Две кнопки с квадратурной диаграммой переключений. Обе защищаются от дребезга как обычные кнопки, причем есть алгоритмы, которые сами по себе бездребезговые, поскольку интервал обработки как раз дает защиту от дребезга.
Я довольно часто ставлю механические энкодеры с осевой кнопкой в разные устройства и всегда и кнопка и энкодер висят на прерывании от системного таймера, совершенно не напрягая общий алгоритм устройства.
Не как обычные кнопки! Там время нужно уменьшать, иначе не комфортно крутить энкодер.
Его же можно крутить не только медленно, но и немного быстрее.
А для кнопок время можно существенно увеличить.
И я не говорил, что алгоритм защиты от дребезга сложный, он не сложный.
Я говорил, что сама программа может быть сложной и вести обработку многих устройств одновременно.
Мне же удобнее в основном цикле работать не с реальным портом, а с регистром который отображает состояние этих портов, ну как в обычном компьютере. То есть в основном цикле программа смотрит в регистр или ячейку памяти тогда когда может по времени и никуда успевать не надо. А прерывания готовят этот регистр или ячейку памяти собирая информацию с портов. Таким образом мы виртуализируем эти порты. В простых коротких программах это может быть излишне, а в больших, где тысячи строк кода это очень удобно.
С моей точки зрения событийный механизм имеет преимущество
Вот я любитель событий и оптимального кода, такой уж я есть.
Кому-то нравится Black Deniels, а кому-то Red Label.
Это очень хорошо, когда есть много различных предложений.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Вобщем-то я с этим и не спорил, просто поставил под сомнение использование прерываний для считывания состояния кнопок. Жирно им будет, и необходимости такой нет. Это ведь нужен будет обработчик прерывания, и диспетчер в нем если прерывание происходит не только от кнопок но еще и от внешнего компаратора который использует тот же порт и одно прерывание вместе с кнопками... вобщем, сложности на ровном месте. А еще с приоритетами разобраться... прерывание от кнопки может возникнуть в неожиданный момент, когда надо ловить другое прерывание с минимальным временем реакции на него.
- fox15
- Первый раз сказал Мяу!
- Сообщения: 28
- Зарегистрирован: Вс май 24, 2009 22:25:36
- Откуда: Russia
- Контактная информация:
Re: Помогите опросить кнопку
Alexeyslav писал(а):Вобщем-то я с этим и не спорил, просто поставил под сомнение использование прерываний для считывания состояния кнопок. Жирно им будет, и необходимости такой нет. Это ведь нужен будет обработчик прерывания, и диспетчер в нем если прерывание происходит не только от кнопок но еще и от внешнего компаратора который использует тот же порт и одно прерывание вместе с кнопками... вобщем, сложности на ровном месте. А еще с приоритетами разобраться... прерывание от кнопки может возникнуть в неожиданный момент, когда надо ловить другое прерывание с минимальным временем реакции на него.
обработчик примитивный примерно десяток процессорных команд, обрабатывает только кнопки. Сложности на ровном месте если и есть то только от компаратора, но я ведь не использовал внешний компаратор в противном случае и алгоритм был бы другой или события от внешнего компаратора сидели бы на другом порту (ну сугубо индивидуально вариантов тысяча).
В том то и дело, что рассчитано на неожиданный момент, тут ведь в реальном времени еще и события о пришедших по USB пакетов из компьютера, которые приходят со скоростью 1.2 Мбит/сек (если точнее то UART поверх USB), шесть прерываний используется.
Все это прекрасно работает не конфликтуя и без пропусков.
Я же это выдрал из прошлого своего проекта, который был на Mega88PA. Проверено ведь в реальной работе.
Ну создает немного сложностей из-за самого факта использования механизма прерывания.
Но это ерунда, десяток процессорных инструкций.
А почему не использовать?
Контроллер набит всякими аппаратными "вкусностями" и удобствами и все это обычно не используется.
Re: Помогите опросить кнопку
Подскажите, почему не работает 3-я кнопка? Первые две отрабатывают все как надо, а третья ни в какую не хочет нажиматься...
Код: Выделить всё
DDRB = 0b11111000;
PORTB= 0b00000111;
switch(count)
{
case 1:
display = 10;
break;
case 2:
display = 20;
break;
case 3:
display = 30;
break;
}
if(!(PINB&1)) // опрашиваем кнопку 1(+)
{
flag1=1; //кнопка нажата (устанавливаем флаг в 1)
_delay_ms(10); //задержка (защита от дребезга)
}
if((flag1==1 )&&(PINB&1)) //условие если кнопка была нажата а потом отпущена
{ count++; flag1=0; } // увеличиваем счетную переменную на единицу и сбрасываем флажок
if(!(PINB&2)) // опрашиваем кнопку 2(+)
{
Flag2=1; //кнопка нажата (устанавливаем флаг в 1)
_delay_ms(10); //задержка (защита от дребезга)
}
if(( Flag2==1 )&&(PINB&2)) //условие если кнопка была нажата о потом отпущена
{ count--; Flag2=0; } // уменьшаем счетную переменную на единицу и сбрасываем флажок
if(!(PINB&3)) // опрашиваем кнопку 3(+)
{
flag3=1; //кнопка нажата (устанавливаем флаг в 1)
_delay_ms(10); //задержка (защита от дребезга)
}
if(( flag3==1 )&&(PINB&3)) //условие если кнопка была нажата о потом отпущена
{ count++; flag3=0; }
if(count>3) count=1;
if(count<1) count=3;
- U235
- Встал на лапы
- Сообщения: 135
- Зарегистрирован: Вт фев 21, 2012 20:42:26
- Откуда: Санкт-Петербург, Россия, Земля
Re: Помогите опросить кнопку
-=eagle=- писал(а):...а третья ни в какую не хочет нажиматься...
Может надо так?
Код: Выделить всё
if(!(PINB&4)) // опрашиваем кнопку 3(+)
{
flag3=1; //кнопка нажата (устанавливаем флаг в 1)
_delay_ms(10); //задержка (защита от дребезга)
}
if(( flag3==1 )&&(PINB&4)) //условие если кнопка была нажата о потом отпущена
{ count++; flag3=0; }
И старайтесь не использовать "магические числа".
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...