0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
1 | |
Правильный опрос клавиатуры13.11.2011, 15:43. Показов 12499. Ответов 15
Метки нет Все метки)
(
Здравствуйте! Имеется четыре подключенных к атмеге кнопки, при помощи которых хочу менять режимы отображения информации на табло, менять время, уставки и т.д. Как в общем подключить и читать кнопки я знаю. Но хочется сделать это грамотно, с устранением дребезга, чтобы один раз нажав на кнопку не было скачкообразного изменения уставки. Т.е. раз нажал, уставка поменялась на "1" а не на 2 и больше. Как это сделать на языке С и может есть ссылки на толковые примеры?
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
|
|
13.11.2011, 15:43 | |
Ответы с готовыми решениями:
15
Опрос матричной клавиатуры Опрос клавиатуры....AVR attini2313 ATtiny2313. ASM. Динамический опрос матричной клавиатуры Как организовать опрос матричной клавиатуры + DS18B20? |
0 / 0 / 0
Регистрация: 15.10.2011
Сообщений: 231
|
|
13.11.2011, 16:46 | 2 |
насколько я понимаю, дребезг на линии можно сгладить конденсатором и даже программных изворотов не понадобится
0
|
0 / 0 / 0
Регистрация: 01.11.2010
Сообщений: 213
|
|
13.11.2011, 17:19 | 3 |
sirj_st
самый простой способ сканировать через опредленные интервалы времени, например 50 мс. Есть более сложные и прикольные способы, но для них организация проги суперциклом будет достаточно геморно. Проще на диспечере или конечных автоматах. Как ты свою прогу планируешь организовать?
0
|
sirvyo
|
|
13.11.2011, 17:27 | 4 |
Дребезг надо просто переждать. Для начала надо установить сам факт нажатия кнопки, это определяется по изменению состояния порта к которому она подключена. Если нажатие произошло, то надо выждать 50-80 миллисекунд и опять проверить состояние порта. За этот промежуток дребезг должен уже успокоиться. Если состояние порта не изменилось, то можно считать нажатие кнопки достоверным. В противном случае, нажатие не достоверно и надо снова повторять цикл опроса клавиатуры.
|
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
13.11.2011, 18:44 | 5 |
Я планирую главный цикл и организовать вызов подпрограммы по прерыванию от таймера. Подпрограмма будет вызываться 100 раз в секунду. Но есть проблема. Мне надо читать показания от DS18B20. Работаю в CVAVR, использую его функцию для чтения Далласа. А ведь перед чтением температуры надо запрещать прерывания. Это значит потерю почти 1 секунды времени, что не есть хорошо. Пришлось эту функцию модифицировать. Ведь функция чтения температуры функция организована так, что посылает код на преобразование, ждет какое-то время (зависит от разрешения датчика) и считывает температуру. Поэтому я разрешил прерывания на время ожидания и перед чтением температуры запретил прерывания. Стало гораздо лучше, но все-равно нажимаю на кнопку и эффект нажатия не всегда заметен. В целом я так и работаю с кнопками, как мне посоветовали выше. Жду в прерывании нажатия на кнопку, выжидаю 50 мс, проверяю что кнопка нажата, затем жду отпускания. Момент отпускания использую для дальнейших действий. Но есть минуса в этом способе - потеря 50 мс, затем "тупое" ожидание отпускания кнопки. И как я сказал не всегда нажатие кнопки распознается. А не долго отпускать кнопку не совсем интересно. Поэтому и спросил как можно по другому организовать опрос кнопки. И вот что подумал, у меня подключена и используется микросхема DS1307. Может опрос термодатчиков делать не в каждом цикле а 1 раз в 5-10 минут?
0
|
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 111
|
|
13.11.2011, 19:12 | 6 |
Заведи таймер на 50 мсек.
В прерывании по таймеру смотри состояние кнопок. Если состояние той или иной кнопки изменилось - ставь однозначно соответствующий кнопке фалжок. Если при следующем прерывании таймера состояние кнопки осталось измененным - считать кнопку нажатой, установить флажок, разрешающий то или иное действие. иначе - сброс флажка, и сканируем заново. Отпускание кнопки, в таком случае, просто очистит флажок нажатия кнопки. (можно аналогично, если 2 прерывания кнопка отпущена - считать ее отжатой). Итого, В прерывании програмка не большая должна получится, ни где в прерывании мега задержек нет.
0
|
0 / 0 / 0
Регистрация: 17.03.2010
Сообщений: 58
|
|
13.11.2011, 21:34 | 7 |
Еще вариант: Заведи еще одну переменную истории в которую записывай состояния кнопок в предыдущий такт прерывания. Если актуальное состояние совпадает с историей - то нажата (или отжата - зависит собственно от значения). Вполне неплохо работает.
ЗЫ: хотя по сути то же самое что в предыдущем посте
0
|
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
13.11.2011, 23:05 | 8 |
Спасибо Всем! Уже сделал и даже работает :)
P.S. Somdor, был я в этом году в Мюнхене. Классный город!
0
|
0 / 0 / 0
Регистрация: 17.03.2010
Сообщений: 58
|
|
13.11.2011, 23:57 | 9 |
![]()
0
|
0 / 0 / 0
Регистрация: 25.06.2011
Сообщений: 140
|
|
14.11.2011, 10:21 | 10 |
я использую везде такой код
Код
#define PORT_LEFT PINB #define PIN_LEFT PB0 static unsykned char debounce_sw_left(void) // опрос кнопки left { static uint16_t state2 = 0; //holds present state state2 = (state2 << 1) | (! bit_is_clear(PORT_LEFT, PIN_LEFT)) | 0xE000; if (state2 == 0xF000) return 1; if (state2 == 0xE000) return 2; return 0; } ниже функция для всех моих кнопок вызывается в прерывании например 1 раз в 10 мс Код
void kbd_scan(void) { unsykned char key = KBD_NOKEY; if (debounce_sw_stomdby() == 1) { key = KBD_STANDBY; } // одиночное срабатывание if (debounce_sw_set() == 1) { key = KBD_SIT; }// одиночное срабатывание if (debounce_sw_regim() == 1) { key = KBD_REGIM; }// одиночное срабатывание if (debounce_sw_stort_stop() == 1) { key = KBD_START_STOP; }// одиночное срабатывание if (debounce_sw_left() >= 1) { key = KBD_LEFT; } // с автоповтором if (debounce_sw_right() >= 1) { key = KBD_RIGHT; } // с автоповтором kbd_key = key; }
0
|
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
14.11.2011, 15:38 | 11 |
dt_omdrew, спасибо огромное за код! Я к сожалению слабоват в битовых операциях на С. Не могли бы Вы прокомментировать код, приведенный ниже? Интересует где именно устранение дребезга, где автоповтор и где триггер? И можно код макроса bit_is_clear?
Код
state2 = (state2 << 1) | (! bit_is_clear(PORT_LEFT, PIN_LEFT)) | 0xE000;
0
|
0 / 0 / 0
Регистрация: 29.08.2011
Сообщений: 84
|
|
16.11.2011, 06:01 | 12 |
![]() Способ детектирования удержания кнопки нажатой на протяжении опред. периода времени (ИМХО) хуже - вдруг у нас старая кнопка которая барахлит при нажатии?? Хотя с другой стороны такой способ более подходящий если устройство должно "отзываться" после того как кнопка была отпущена. Пример дать не могу - слишком давно это делал (через векторы прерываний и флажки - сложного ничего нет).
0
|
0 / 0 / 0
Регистрация: 02.11.2010
Сообщений: 499
|
|
16.11.2011, 16:04 | 13 |
![]() Запретил прерывания , запустил преобразование температуры, разрешил прерывания (несколько милисек) Затем секунду что-то делаешь(можно клавиатуру опрашивать). Через секунду перед чтением далласа запретил прерывания. Прочитал данные и опять разрешил прерывания.
0
|
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
16.11.2011, 16:10 | 14 |
![]() ![]()
0
|
0 / 0 / 0
Регистрация: 25.06.2011
Сообщений: 140
|
|
17.11.2011, 15:12 | 15 |
![]() переменная state2 заметьте 2 байта занимает нажали на кнопку эта переменная стала заполняться 1 (state2 << 1) а в правой части идет сравнение с Е000 то есть удержание кнопки было 24 цикла опроса вот вам подавление дребезга как анализировать автоповтор это или нет я привл во второй части кода см внимательней там коменты есть и увидите разницу под триггерным эффектом я подразумевал нажали и пока не отпустили повторного нажатия не будет макрос bit_is_clear есть в WinAvr я не знаю в чем пишите вы если в CV то там по моему можно просто писать if (PORTx.0 == 0) или использовать макросы типа таких #define BIT(x) (1 << (x)) #define SITBITS(x,y) ((x) |= (y)) #define CLEARBITS(x,y) ((x) &= (~(y))) #define SITBIT(x,y) SITBITS((x), (BIT((y)))) #define CLEARBIT(x,y) CLEARBITS((x), (BIT((y)))) #define BITSIT(x,y) ((x) & (BIT(y))) #define BITCLEAR(x,y) !BITSIT((x), (y)) #define BITSSIT(x,y) (((x) & (y)) == (y)) #define BITSCLEAR(x,y) (((x) & (y)) == 0) #define BITVOT(x,y) (((x)>>(y)) & 1) ваша замена #define BITSCLEAR(x,y) (((x) & (y)) == 0) надеюсь понятно обьяснил
0
|
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
|
|
17.11.2011, 16:07 | 16 |
Спасибо огромное! Вы очень понятно объяснили!
0
|
17.11.2011, 16:07 | |
Помогаю со студенческими работами здесь
16
Опрос клавиатуры 3х4 и вывод нажатой кнопки AT90S8515
Диагностика, опрос и тестирование клавиатуры
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |