0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
1

Правильный опрос клавиатуры

13.11.2011, 15:43. Показов 12499. Ответов 15
Метки нет (Все метки)

Здравствуйте! Имеется четыре подключенных к атмеге кнопки, при помощи которых хочу менять режимы отображения информации на табло, менять время, уставки и т.д. Как в общем подключить и читать кнопки я знаю. Но хочется сделать это грамотно, с устранением дребезга, чтобы один раз нажав на кнопку не было скачкообразного изменения уставки. Т.е. раз нажал, уставка поменялась на "1" а не на 2 и больше. Как это сделать на языке С и может есть ссылки на толковые примеры?
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.11.2011, 15:43
Ответы с готовыми решениями:

Опрос матричной клавиатуры
Здравствуйте. Подключил к Pinboard 1.1 (atmega16) матричную мембранную клавиатуру 4х4, к PORTA...

Опрос клавиатуры....AVR attini2313
Доброго времени суток=) Помогите пож. допилить прогу , делаю динамический опрос матричной...

ATtiny2313. ASM. Динамический опрос матричной клавиатуры
Помогите написать программу на асм для микроконтроллера аттини 2313 или атмега8 динамический опрос...

Как организовать опрос матричной клавиатуры + DS18B20?
Господа, подскажите, пожалуйста, каким образом организовать опрос матричной клавиатуры и при этом...

15
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
Цитата Сообщение от sirj_st
P.S. Somdor, был я в этом году в Мюнхене. Классный город!
Мне тоже нравится :) Особенно близость к альпам ;)
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
Цитата Сообщение от sirj_st
Здравствуйте! Имеется четыре подключенных к атмеге кнопки, при помощи которых хочу менять режимы отображения информации на табло, менять время, уставки и т.д. Как в общем подключить и читать кнопки я знаю. Но хочется сделать это грамотно, с устранением дребезга, чтобы один раз нажав на кнопку не было скачкообразного изменения уставки. Т.е. раз нажал, уставка поменялась на "1" а не на 2 и больше. Как это сделать на языке С и может есть ссылки на толковые примеры?
ИМХО самый правильный и четкий способ - сразу обрабатывать прерывание при первом же касании. потом около 100мс игнорируем любые последующие нажатия.

Способ детектирования удержания кнопки нажатой на протяжении опред. периода времени (ИМХО) хуже - вдруг у нас старая кнопка которая барахлит при нажатии?? Хотя с другой стороны такой способ более подходящий если устройство должно "отзываться" после того как кнопка была отпущена.

Пример дать не могу - слишком давно это делал (через векторы прерываний и флажки - сложного ничего нет).
0
0 / 0 / 0
Регистрация: 02.11.2010
Сообщений: 499
16.11.2011, 16:04 13
Цитата Сообщение от sirj_st
Я планирую главный цикл и организовать вызов подпрограммы по прерыванию от таймера. Подпрограмма будет вызываться 100 раз в секунду. Но есть проблема. Мне надо читать показания от DS18B20. Работаю в CVAVR, использую его функцию для чтения Далласа. А ведь перед чтением температуры надо запрещать прерывания. Это значит потерю почти 1 секунды времени, что не есть хорошо.
А зачем ждать секунду?
Запретил прерывания , запустил преобразование температуры, разрешил прерывания (несколько милисек)
Затем секунду что-то делаешь(можно клавиатуру опрашивать).
Через секунду перед чтением далласа запретил прерывания. Прочитал данные и опять разрешил прерывания.
0
0 / 0 / 0
Регистрация: 04.08.2011
Сообщений: 30
16.11.2011, 16:10 14
Цитата Сообщение от komtrottir
А зачем ждать секунду?
Цитата Сообщение от sirj_st
Это значит потерю почти 1 секунды времени, что не есть хорошо. Пришлось эту функцию модифицировать. Ведь функция чтения температуры функция организована так, что посылает код на преобразование, ждет какое-то время (зависит от разрешения датчика) и считывает температуру. Поэтому я разрешил прерывания на время ожидания и перед чтением температуры запретил прерывания. Стало гораздо лучше...
В общем я так и сделал. Стало супер. Клавиатура опрашивается очень хорошо. На дребезг пауза 10 мс.
0
0 / 0 / 0
Регистрация: 25.06.2011
Сообщений: 140
17.11.2011, 15:12 15
Цитата Сообщение от sirj_st
dt_omdrew, спасибо огромное за код! Я к сожалению слабоват в битовых операциях на С. Не могли бы Вы прокомментировать код, приведенный ниже? Интересует где именно устранение дребезга, где автоповтор и где триггер? И можно код макроса bit_is_clear?
Код:
state2 = (state2 << 1) | (! bit_is_clear(PORT_LEFT, PIN_LEFT)) | 0xE000;

переменная 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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.11.2011, 16:07
Помогаю со студенческими работами здесь

Опрос клавиатуры 3х4 и вывод нажатой кнопки AT90S8515
Написана программа на С, для такой вот схемы писал честно говоря не я, но для этой схемы. Суть...

Опрос клавиатуры
Нужна программа опроса клавиатуры, т.е. я нажимаю клавишу на клавиатуре и он мне выводит ASCII код...

Диагностика, опрос и тестирование клавиатуры
Все привет! Помогите пожалуйста с моей проблемой (((( 1 курс. По ассемблеру курсовик на тему: ...

Первое знакомство,опрос клавиатуры
Всем добрый день. Давно хотел сесть за этот бейсик. поставил q basic v.1.0 работает из виндовс....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru