Пн июн 24, 2013 01:21:14
Я думаю что не достаточно ОДНОГО защелкивания....Alexeyslav писал(а):По факту достаточно ОДНОГО защелкивания. Ведь в процессе дребезга на момент защелкивания может быть считано только одно из двух 1 или 0. Но поскольку конкретно этот момент считывания обрамляют разные уровни 1 и 0 либо 0 и 1 то каким бы ни было считывание в момент дребезга оно лишь приведет к отставанию считывания реального состояния кнопки максимум на время одного опроса.
//#######################################################################################################################
//#
//# ФУНКЦИИ РАБОТЫ С КЛАВОЙ
//#
//# в начале проинитить библиотеку вызовом BtnInit();
//# организовать вызов из прерывания с частотой 100Гц - функцию BtnExe();
//# чтение значения состояния флагов кнопок производится с помощью функции BtnGet();
//# например так:
//# char BtnMask = BtnGet();
//# if (BtnMask & BTN_SHRT_UP) {....ветка короткого нажатия кнопки UP}
//# if (BtnMask & BTN_SHRT_DN) {....ветка короткого нажатия кнопки DN}
//# if (BtnMask & BTN_LONG_RIGHT) {....ветка длинного нажатия кнопки RIGHT}
//# и т.д.
//#
//#######################################################################################################################
//настройка параметров работы функций
#define BTN_LOCK_TIME 30 /*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME 1000 /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
#define BTN_PORT PORTC /*порт чтения кнопок*/
#define BTN_DDR DDRC
#define BTN_PIN PINC
#define BTN_LINE_UP (1<<0) /*пины чтения кнопок*/
#define BTN_LINE_DN (1<<1)
#define BTN_LINE_LEFT (1<<2)
#define BTN_LINE_RIGHT (1<<3)
//глобальные переменные
volatile uint8_t BtnFlags; //байт флагов нажатия кнопки
#define BTN_SHRT_UP (1<<0) /*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN (1<<1) /*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_LEFT (1<<2) /*бит короткого нажатия кнопки left*/
#define BTN_SHRT_RIGHT (1<<3) /*бит короткого нажатия кнопки right*/
#define BTN_LONG_UP (1<<4) /*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN (1<<5) /*бит длинного нажатия кнопки dn*/
#define BTN_LONG_LEFT (1<<6) /*бит длинного нажатия кнопки left*/
#define BTN_LONG_RIGHT (1<<7) /*бит длинного нажатия кнопки right*/
//#######################################################################################################################
//функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_LEFT| BTN_LINE_RIGHT); //на ввод
BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_LEFT| BTN_LINE_RIGHT); //подтяжка вкл
}
//----------
//функция чтения данных о нажатии кнопок
char BtnGet (void)
{
cli ();
char temp = BtnFlags;
BtnFlags = 0;
sei ();
return temp;
}
//----------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
static unsigned char BtnLockBit; //ащелка (защита от дребезга)
static unsigned char BtnLockCoun; //счетчик защелки (защита от дребезга)
static unsigned char BtnLongCoun; //счетчик длинного нажатия
static unsigned char BtnLastState; //последнее состояние кнопок перед отпусканием
char mask = 0;
if (! (BTN_PIN & BTN_LINE_UP)) mask = BTN_SHRT_UP;
if (! (BTN_PIN & BTN_LINE_DN)) mask = BTN_SHRT_DN;
if (! (BTN_PIN & BTN_LINE_LEFT)) mask = BTN_SHRT_LEFT;
if (! (BTN_PIN & BTN_LINE_RIGHT)) mask = BTN_SHRT_RIGHT;
if (mask){ //опрос состояния кнопки
if (BtnLockCoun < (BTN_LOCK_TIME/10)){ //клавиша нажата
BtnLockCoun++;
return; //защелка еще не дощитала - возврат
}
BtnLastState = mask;
BtnLockBit =1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
BtnFlags |= (BtnLastState<<4); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
}
else{ //клавиша отжата
if (BtnLockCoun){
BtnLockCoun --;
return; //защелка еще не обнулилась - возврат
}
if (! BtnLockBit) //СТАТИЧЕСКИЙ ВОЗВРАТ
return;
BtnLockBit =0; //отжатие зафиксировано
if (BtnLongCoun < (BTN_LONG_TIME/10))
BtnFlags |= BtnLastState; //установка бита короткого нажатия
BtnLongCoun = 0; //сброс счетчика длительности нажатия
}
}
//#######################################################################################################################
Пн июн 24, 2013 10:45:48
Вт июл 02, 2013 22:02:15
Да, например плата компактная и помехи ей не страшны..... но если кнопки расположены не на плате, и подключены шлейфом.... Вот вам и подвох.....Alexeyslav писал(а):Вероятность такого события довольно низка. А если у вас в условиях применения схемы так сильно прут помехи, боюсь там проблем будет выше крыши не только с кнопками. В крайнем случае, импульсные помехи сглаживает обычная RC-цепочка(но она не избавляет от дребезга реальной кнопки).
Вт июл 02, 2013 22:46:20
Пт ноя 08, 2013 15:27:40
/***
Управляем светодиодом с помощью энкодера ***/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
EEMEM uint8_t ee_zn, ee_zc;//* переменная размером в 2 байта в EEPROM
unsigned char my_y,my_b;
volatile char pwm_counter, button ;
// Обработчик прерывания int0
ISR(SIG_INTERRUPT0)
{
_delay_us(50);
if((PIND & (1 << PD2))==0)
{
_delay_us(50);
if((PIND & (1 << PD0))==0)
{
if(button == 0) //
{
my_y--; if(my_y < 1) my_y = 1;
}
if(button == 1) //
{
my_b--; if(my_b < 1) my_b = 1;
}
}
else
{
if(button == 0) //
{
my_y++; if(my_y > 65) my_y = 65;
}
if(button == 1) //
{
my_b++; if(my_b > 65) my_b = 65;
}
}
}
GIFR = (1<<INTF0);
return;
}
ISR (TIMER0_OVF_vect)
{
{
if (button == 0)
{
if (pwm_counter++ > 65)
{
PORTB = 0x00;
pwm_counter = 0;
}
if (pwm_counter > my_y)
PORTB |= (1 << PB0);
}
}
{
if (button == 1)
{
if (pwm_counter++ > 65)
{
PORTB = 0x00;
pwm_counter = 0;
}
if (pwm_counter > my_b)
PORTB |= (1 << PB0);
}
}
}
// Главная функция
int main (void)
{
DDRB |= (1 << PB0)|(1 << PB1); // выходы
PORTB = 0x00;
DDRD |= (1 << PD3)|(0 << PD2)|(0 << PD1)|(0 << PD0); // входы
PORTD |= (1 << PD2)|(1 << PD1)|(1 << PD0)|(0 << PD3); // подключаем подтягивающие резисторы
TIMSK |= (1 << TOIE0); // разрешение прерывания по таймеру0
TCCR0 |= (1 << CS00);
MCUCR |= (0 << ISC00)|(1 << ISC01); // прерывание по заднему фронту INT0(по спаду импульса)
GIFR |= (1 << INTF0); // очищаем флаг внешнего прерывания
GICR |= (1 << INT0); // разрешаем внешние прерывания INT0
sei(); //глобально разрешаем прерывания
while(1)
{
while(3)
{
if
((PIND & (1 << PD3))==0) break;
button = 0;
my_y = eeprom_read_byte(&ee_zn);//чтение первой переменной
_delay_ms(1000);
eeprom_write_byte(&ee_zn, my_y);//запись первой переменной
}
button = 1;
my_b = eeprom_read_byte(&ee_zc);//чтение второй переменной
_delay_ms(1000);
eeprom_write_byte(&ee_zc, my_b);//запись второй переменной
}
}
Вт дек 17, 2013 01:08:10
Уже разобрался?Naman_S писал(а):как сделать запись по нажатию кнопки так и не смог разобраться
Пн фев 03, 2014 21:53:03
Пн фев 03, 2014 23:25:36
Naman_S писал(а):shads нет, если поможешь буду благодарен
Пн фев 03, 2014 23:31:00
Вт фев 04, 2014 01:15:51
Вт фев 04, 2014 01:18:45
Alexeyslav писал(а):Так собственно проблема в чем, отловить момент нажатия кнопки, или записать в EEPROM?
Момент отловить - постоянно сравнивать состояние кнопки с предыдущим, моменты нажатия и отпускания отлавливаются на раз-два, а процедура записи в EEPROM приведена прямо в даташите на контроллер, в виде куска кода. Да, перед записью стоит убедится что записываешь другое значение а не то что там уже есть - чтобы зря ресурс ячеек не расходовать, особенно во время отладки.
Пн апр 21, 2014 20:08:33
if (button==0)
{
_delay_ms (bounce);
while (button==0) {};
if(++mode>=5)mode=0;
}
Ср апр 23, 2014 23:00:09
#include <mega8.h>
#include <delay.h>
void main(void)
{
PORTB=0x00; // PORTB - выход
DDRB=0x01;
PORTC=0x01; // PORTC - вход
DDRC=0x00;
while (1)
{
unsigned char a=0; // переменной а присвоить 0
if(PINC.0==0) // если кнопка нажата
{
a++; // инкриминируем а
if(a==2) // если а равно 2 (кнопка нажата 2 раза)
{
PORTB.0=1; // выводим 1
a=0; // обнуляем а
}
}
}
}
Ср апр 23, 2014 23:44:53
if(PINC.0==0) // если кнопка нажата
{
delay_ms (10);
while (PINC.0==0) {};
a++; // инкриминируем а
if(a==2) // если а равно 2 (кнопка нажата 2 раза)
{
PORTB.0=1; // выводим 1
a=0; // обнуляем а
}
}
Чт апр 24, 2014 00:32:45
Чт апр 24, 2014 08:09:38
Alexeyslav писал(а):Вам кроме подсчета нажатий надо бороться с дребезгом(прошлый код был попыткой это сделать) и ОТЛАВЛИВАТЬ моменты нажатия и отпускания
Чт апр 24, 2014 08:22:42
Чт апр 24, 2014 09:20:22
Внимательно прочтите сообщение которое перед вашим...как ОТЛАВЛИВАТЬ моменты нажатия
Чт апр 24, 2014 22:13:06
Alexeyslav писал(а):Внимательно прочтите сообщение которое перед вашим...
#include <mega8.h>
#include <delay.h>
char s=0; // переменная s=0
interrupt [EXT_INT0] void ext_int0_isr(void)//внешние прерывания
{
s++; //инкриминируем s
if(s==4) // если s=4(а не 2, как нужно)
{
PORTB.0=0; // 0 на PORTB.0=0
s=0; // обнулить s
}
}
void main(void)
{
DDRB=0x01;
PORTB.0=1;
PORTC=0x01;
DDRC=0x00;
PORTD=0x04;
DDRD=0x00;
GICR|=0x40;
MCUCR=0x01;
GIFR=0x40;
UCSRB=0x00;
SFIOR=0x00;
SPCR=0x00;
TWCR=0x00;
// Global enable interrupts
#asm("sei")
while (s==0) // пока s=0
{
PORTB.0=1;
delay_ms(5000);
}
}
Пт апр 25, 2014 10:23:46