sanyo.95 писал(а):ARV писал(а):в это время контакт дребезжит
Большое спасибо за столь поняьный ответ. Не подскажете как избавиться от дребезга, я так понимаю нужно исползовать таймер?
если вы начинающий - зачем вам сложности с таймером? я уже так много раз рассказывал про кнопки, что скоро тошнить будет... но все-таки повторюсь.
алгоритм опроса кнопки должен быть следующим:
1. считываем состояние кнопки (или кнопок, если их несколько) в какую-то переменную, пусть это будет key
2. делаем задержку на 10-15 миллисекунд, за которые дребезг обычно должен кончиться
3. снова считываем состояние кнопки и сравниваем его с key
4. если оба значения одинаковы - то key и будет соответствовать текущему состоянию кнопки (кнопок), можно его обрабатывать
5. если значения разные - то мы считаем, что дребезг еще не кончился и тогда вместо key выдаем 0, что должно означать отсутствие нажатия кнопок.
на языке Си это может выглядеть так:
Код: Выделить всё
// макрос для задержки подалвения дребезга в миллисекундах
#define DEBOUNCE 15
uint8_t get_key_code(void); // эта функция вернет состояние кнопок
// функия опроса кнопок, вернет 0, если нет нажатий, не ноль - если есть
uint8_t get_key(void){
uint8_t key;
key = get_key_code();
delay_ms(DEBOUNCE);
if(key == get_key_code())
return key;
else
return 0;
}
вы всегда используете get_key(), если хотите определить состояние кнопки или кнопок. особо заострю ваше внимание на функции get_key_code(), для которой я не показал реализацию. дело в том, что эта функция может быть разной для одной кнопки, пяти-восьми кнопок, для матрицы 4х4 или даже более - в каждом случае она должна быть своя. можно заменить ее макросом, если работаем только с 1-8 кнопками. вот пример для опроса единственной кнопки, висящей на 0-ом пине PORTB:
Код: Выделить всё
uint8_t get_key_code(void){
return ~PINB & _BV(0);
}
так как обычно кнопки с порта вешают на землю, то нажатому состоянию соответствует 0 в соответствующем пине. чтобы не нарушать логику, я инвертирую это значение, чтобы не нажатому состоянию соответствовал 0, а нажатому 1.
если вы повесили 4 кнопки на PORTB, то поступаете вот так:
Код: Выделить всё
// определяем константы для каждой кнопки
#define KEY1 _BV(PB0)
#define KEY2 _BV(PB1)
#define KEY3 _BV(PB2)
#define KEY4 _BV(PB3)
// а вот так мы обозначаем сразу все наши кнопки
#define ALL_KEY (KEY1 | KEY2 | KEY3 | KEY4)
uint8_t get_key_code(void){
return ~PINB & ALL_KEY;
}
в этом случае в своей программе вы вот так обрабатываете все свои 4 кнопки:
Код: Выделить всё
// где-то в глубине своей программы
switch(get_key()){
case KEY1: // тут обработка кнопки 1
break;
case KEY2: // тут обработка кнопки 1
break;
case KEY3: // тут обработка кнопки 1
break;
case KEY4: // тут обработка кнопки 1
break;
case KEY1 | KEY3: // тут обработка одновременного нажатия сразу 2 кнопок
break;
default:
// а тут обработка всех прочих вариантов, в том числе отсутствия нажатия
}
как видите, все элементарно просто, и никакие таймеры не нужны. когда заматереете, как программист, тогда, возможно, начнете обрабатывать кнопки и с прерываниями и таймерами, но лично мне в огромном количестве поделок практически никогда это не требовалось...
P.S. да, примеры я привел с ориентацией на
avr-gcc, если вы любитель
CodeVision, вам нужно перед всем этим добавиь пару строчек:
Код: Выделить всё
typedef unsigned char uint8_t;
#define _BV(x) (1<<(x))