Опрос кнопок микроконтроллером

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вт окт 09, 2012 14:09:39

Сообщение drac0Sha »

Ребят, подскажите, пожалуйста, как на си обработать одновременное нажатие двух кнопок
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Код: Выделить всё

if(Button1 && Button 2)
{
.............
} 
Ставим плюсы: )
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

:)) Собственно, какой вопрос, такой и ответ.

drac0Sha, так-же как и одну, только обрабатываем две :)
Контактная информация:
Встал на лапы
Сообщения: 114
Зарегистрирован: Чт ноя 24, 2011 12:39:13

Сообщение Marchello »

Уважаемые форумчане, подскажите какой вариант из предложенных наиболее удобный! И желательно бы хотелось услышать как плюсы так и минуса каждой схемы подключения!
Схема подключения кнопок _ 1.JPG
(94.61 КБ) 566 скачиваний
Схема подключения кнопок _ 2.JPG
(166.27 КБ) 790 скачиваний
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

1)
+проще обработка с точки зрения программы
+можно обрабатывать любую комбинацию одновременно нажатых кнопок
-нужно много ног для подключения
-для аппаратного антидребезга нужны RC-цепочки для каждой кнопки
2)
+всего одна нога контроллера
-немного сложнее обработка кнопок
-нажатие более одной кнопки может обработаться как нажатие другой кнопки
Реклама
Встал на лапы
Сообщения: 114
Зарегистрирован: Чт ноя 24, 2011 12:39:13

Сообщение Marchello »

Спасибо за оперативный ответ!
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Второй вариант можно использовать только если в МК есть АЦП
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Второй вариант можно использовать только если в МК есть АЦП
или шим+аналоговый компаратор.
Контактная информация:
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 11, 2012 19:50:50

Сообщение vite »

Сильно не пинайте я только учусь помогите разобраться по чему отслеживания кнопки не происходит
LIST P=PIC16F628A
__CONFIG H'3F69'

STATUS EQU H'03'
TRISA EQU H'05'
PORTA EQU H'05'
TRISB EQU H'06'
PORTB EQU H'06'

org 0 ; начало программы
; подготовительные моменты
bsf STATUS,5 ; переход в Банк 1
movlw b'00011111'
movwf TRISA
clrf TRISB
bcf STATUS,5 ; переход назад в Банк 0
clrf PORTB ; очистка порта
; отслеживание нажатия кнопки
m1 btfsc PORTA,2 ; бит-проверка ножки RA2
goto m1
movlw .255
movwf PORTB
clrf PORTB
goto m1

end ; конец программы
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Все правильно сделано, считывается состояние, сейчас собрал проект если кнопка нажата-моргает портом B в протеусе. Если не нажата - не моргает. Возможно просто вы не видите этого в реале так как потому что нет задержки перед выключением порта
Попробуйте так проверить, так просто копируется состояние ноги RA2 в порт B
Спойлер

Код: Выделить всё

LIST P=PIC16F628A
__CONFIG H'3F69'

STATUS EQU H'03'
TRISA EQU H'05'
PORTA EQU H'05'
TRISB EQU H'06'
PORTB EQU H'06'

org 0 ; начало программы 
; подготовительные моменты
bsf STATUS,5 ; переход в Банк 1
movlw b'00011111'
movwf TRISA
clrf TRISB
bcf STATUS,5 ; переход назад в Банк 0
clrf PORTB ; очистка порта
; отслеживание нажатия кнопки 
m1: btfsc PORTA,2 ; бит-проверка ножки RA2
goto m2
clrf PORTB
goto m1
m2 movlw .255
movwf PORTB
goto m1
end ; конец программы
Контактная информация:
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 11, 2012 19:50:50

Сообщение vite »

Протеуса у меня нет. Попробовал ваш вариант в МК . Глуха как в танке ,а в моем варианте горят все порты В сразу как подашь питания. Может надо ка кто по другому биты конфигурации выставить ?
Открыл глаза
Сообщения: 54
Зарегистрирован: Чт дек 13, 2012 19:31:00
Откуда: Санкт-Петербург

Сообщение zzontt »

День добрый, пытаюсь организовать опрос двух кнопок, взял пример из этого сообщения
Аlex писал(а):Ну чтож, коли пошла такая пьянка, подкину и я своих дровишек в костёрчик )
Раз тут собрались одни АВРщики :)), пришлось поставить CV и черкнуть на нём примерчик обработки кнопок. CV взял из-за генератора кода, т.к. не хочется лезть в даташит на совершенно незнакомые мне МК. В общем, за им генерируемый код меня не пинать :)) . Остальное, что касается моей писанины - обсуждаем, критикуем, закидываем помидорами, .... :)))
В архиве проект + файл всеми любимого протеуса:
butt.rar
Программа хорошо комментирована, так что, думаю, вопросов не возникнет.
Если кому будет интересно, могу добавить обработку длинного нажатия.
и переделал под себя, но вот какая загвоздка, все работает если я организовываю опрос либо кнопки 1 либо кнопки 2, но когда пытаюсь сделать так что бы работал опрос 2х кнопок, то почему то программа реагирует только на нажатие кнопки 1, подскажите в чем может быть проблема, что надо исправить что бы была реакция на нажатие обоих кнопок. Код моей программы ниже.
Спойлер

Код: Выделить всё

/*****************************************************
#include <mega16.h>
#define DATA_STOLB PORTA.1 
#define CLK_STOLB PORTA.2 
#define LATCH_STOLB PORTA.3 
#define DATA_STR PORTC.4 
#define CLK_STR PORTC.5 
#define LATCH_STR PORTC.6 

//_______________
#define PORT_BUTT_1     PIND    // Порт кнопки №1
#define PIN_BUTT_1      2       // Номер бита порта кнопки №1

#define ACT_BUTT_LEV_1    0       // Активный уровень нажатых кнопок
#define ACT_BUTT_LEV_2    0

#define PORT_BUTT_2     PIND    // Порт кнопки №2
#define PIN_BUTT_2      3       // Номер бита порта кнопки №2
//________________________
unsigned char  str=0b10000000, maska_str;
unsigned int stolb=0b0111111111111111, maska_stolb;
//________________________________
typedef struct{
    unsigned cur:   1;      // Текущее состояние
    unsigned prev:  1;      // Предыдущее состояние
    unsigned down:  1;      // Была нажата
    unsigned up:    1;      // Была отжата
}tButt1;
volatile tButt1  mButt_1 = {0,!ACT_BUTT_LEV_1,0,0};    // Объявляем структуру mButt_1 для нашей кнопки и иним её.

typedef struct{
    unsigned cur:   1;      // Текущее состояние
    unsigned prev:  1;      // Предыдущее состояние
    unsigned down:  1;      // Была нажата
    unsigned up:    1;      // Была отжата
}tButt2;
volatile tButt2  mButt_2 = {0,!ACT_BUTT_LEV_2,0,0};    // Объявляем структуру mButt_2 для нашей кнопки и иним её.
//________________________________

interrupt [TIM1_OVF] void timer1_ovf_isr(void){
static unsigned char cnt_ms_butt=20;    // Счётчик для формирования периода в 20 мс.
TCNT1 -= 4000;          // Перезапускаем таймер на 1 мс.
//----------------------//
if(!--cnt_ms_butt)
{     // Формируем 20-ти миллисек. периоды
    cnt_ms_butt=20;
    mButt_1.cur = (PORT_BUTT_1&(1<<PIN_BUTT_1))!=0;                         // Считываем текущее значение вывода.
                                                                            // Дальше работаем с этим битом, т.к. порт может измениться в любой момент.
    if((mButt_1.cur==ACT_BUTT_LEV_1) && (mButt_1.prev!=ACT_BUTT_LEV_1))     // Если текущее значение - "нажата" и предыдущее - "не нажата"
        mButt_1.down = 1;                                                   // Устанавливаем флаг down
    if((mButt_1.cur!=ACT_BUTT_LEV_1) && (mButt_1.prev==ACT_BUTT_LEV_1))     // Если текущее значение - "не нажата" и предыдущее - "нажата"
        mButt_1.up = 1;                                                     // Устанавливаем флаг up
    mButt_1.prev=mButt_1.cur;                                               // Сохраняем текущее значение. Оно для следующего входа будет предыдущим 
   
    if((mButt_2.cur==ACT_BUTT_LEV_2) && (mButt_2.prev!=ACT_BUTT_LEV_2))     // Если текущее значение - "нажата" и предыдущее - "не нажата"
        mButt_2.down = 1;                                                   // Устанавливаем флаг down
    if((mButt_2.cur!=ACT_BUTT_LEV_2) && (mButt_2.prev==ACT_BUTT_LEV_2))     // Если текущее значение - "не нажата" и предыдущее - "нажата"
        mButt_2.up = 1;                                                     // Устанавливаем флаг up
    mButt_2.prev=mButt_2.cur;
}
}
/******************************************************************/
//Сдвиг по стобцам
void sdvig_stolb (void)
{
maska_stolb=0x8000;

        do
        { // начало цикла
        if(stolb & maska_stolb)      // если в результате умножения маски и числа получилось ненулевое значение
        {
        DATA_STOLB=1;                // выводим в порт 1
        #asm("nop");         
        CLK_STOLB=1;
        #asm("nop");
        CLK_STOLB=0;        
        #asm("nop");
        }
        else
        {
        DATA_STOLB=0;                // иначе 0 
        #asm("nop");
        CLK_STOLB=1;
        #asm("nop");
        CLK_STOLB=0;        
        #asm("nop");
        } 
        maska_stolb>>=1;             // сдвигаем маску вправо на 1 разряд 
        }
        while(maska_stolb!=0x000);   // цикл выполняется, пока не выдадим  16 разрядов и //значение маски станет 0x0000 
        LATCH_STOLB=1;               // Импульс на Latch clock
        #asm("nop");
        LATCH_STOLB=0; 
        }

//Сдвиг по строкам
void sdvig_str (void)
{
maska_str=0x80;

        do
        { // начало цикла
        if(str & maska_str)          // если в результате умножения маски и числа получилось ненулевое значение
        {
        DATA_STR=1;                  // выводим в порт 1
        #asm("nop");         
        CLK_STR=1;
        #asm("nop");
        CLK_STR=0;        
        #asm("nop");
        }
        else
        {
        DATA_STR=0;                  // иначе 0 
        #asm("nop");
        CLK_STR=1;
        #asm("nop");
        CLK_STR=0;        
        #asm("nop");
        } 
        maska_str>>=1;              // сдвигаем маску вправо на 1 разряд 
        }
        while(maska_str!=0x00);     // цикл выполняется, пока не выдадим  16 разрядов и //значение маски станет 0x0000 
        LATCH_STR=1;                // Импульс на Latch clock
        #asm("nop");
        LATCH_STR=0; 
        }
//инициализация МК
void inMK(void)
{
// Port A initialization
PORTA=0x00;
DDRA=0x0E;
// Port B initialization
PORTB=0x00;
DDRB=0x00;
// Port C initialization
PORTC=0x00;
DDRC=0x70;
// Port D initialization
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;
// USART initialization
// USART disabled
UCSRB=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC disabled
ADCSRA=0x00;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// TWI disabled
TWCR=0x00;
}
//основная программа
void main(void)
{
inMK();
#asm("sei")
while (1)
{
if(mButt_2.up){                         // Если кнопка была нажата -> отжата
    mButt_2.up=0;                       // Сбрасываем флаг       
    str=(str >> 1) | (str << 7);        // Двигаем диод по строкам
}                                    
if(mButt_1.up){                         // Если кнопка была нажата -> отжата
    mButt_1.up=0;                       // Сбрасываем флаг       
    stolb=(stolb >> 1) | (stolb << 15); // Двигаем диод по столбцам
}
   
sdvig_stolb();
sdvig_str();
      
//buttob_stolb();
//buttob_str();        

}
}
Не бейте за глупости, я только учусь)
Контактная информация:
Встал на лапы
Сообщения: 106
Зарегистрирован: Пн мар 26, 2012 05:25:06

Сообщение Совесть »

Не нашел записи в mButt_2.cur.
Открыл глаза
Сообщения: 54
Зарегистрирован: Чт дек 13, 2012 19:31:00
Откуда: Санкт-Петербург

Сообщение zzontt »

Совесть писал(а):Не нашел записи в mButt_2.cur.
Действительно, был не внимателен пропустил строчку, вопрос закрыт.
Спасибо.
Не бейте за глупости, я только учусь)
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Кстати, для каждой кнопки не нужно объявлять свой тип, достаточно одного:

Код: Выделить всё

typedef struct{
    unsigned cur:   1;      // Текущее состояние
    unsigned prev:  1;      // Предыдущее состояние
    unsigned down:  1;      // Была нажата
    unsigned up:    1;      // Была отжата
}tButt;

volatile tButt  mButt_1 = {0,!ACT_BUTT_LEV,0,0};
volatile tButt  mButt_2 = {0,!ACT_BUTT_LEV,0,0};

Контактная информация:
Открыл глаза
Сообщения: 54
Зарегистрирован: Чт дек 13, 2012 19:31:00
Откуда: Санкт-Петербург

Сообщение zzontt »

Аlex писал(а):Кстати, для каждой кнопки не нужно объявлять свой тип, достаточно одного
Спасибо, буду знать.
Последний раз редактировалось Аlex Чт мар 21, 2013 09:30:26, всего редактировалось 1 раз.
Причина: -
Не бейте за глупости, я только учусь)
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Пытаюсь сделать обработку длительного нажатия кнопки. Делаю вот так вот

Код: Выделить всё

interrupt [TIM1_OVF] void timer1_ovf_isr(void){
static unsigned char cnt_ms_butt=20;    // Счётчик для формирования периода в 20 мс.
TCNT1 -= 4000;          // Перезапускаем таймер на 1 мс.
//----------------------//
if(!--cnt_ms_butt){     // Формируем 20-ти миллисек. периоды
    cnt_ms_butt=20;
    mButt_1.cur = (PORT_BUTT_1&(1<<PIN_BUTT_1))!=0;                 // Считываем текущее значение вывода.
                                                                    // Дальше работаем с этим битом, т.к. порт может измениться в любой момент.
    if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV) && timer<10) // Если текущее значение - "нажата" и предыдущее - "не нажата"
        mButt_1.down = 1;                                                   // Устанавливаем флаг down
    if((mButt_1.cur!=ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)&& timer<10) // Если текущее значение - "не нажата" и предыдущее - "нажата"
        mButt_1.up = 1;                                                     // Устанавливаем флаг up
	if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)){ 
		timer++;
		if(timer>10) mButt_1.but_long = 1;                          
      }  
   		
    mButt_1.prev=mButt_1.cur;                                       // Сохраняем текущее значение. Оно для следующего входа будет предыдущим
}
//----------------------//
}
но тут получается что при нескольких коротких нажатий переменная timer доходит до 10 и устанавливается флаг как этого избежать ? И вообще в правильную сторону копаю?
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Код: Выделить всё

if(mButt_1.cur){
  if(++mButt_1.timer>=50)   mButt_1.butt_long=1;
  else                      mButt_1.butt_long=0;
}
else{
  mButt_1.butt_long=0;
  mButt_1.timer=0;
}
.timer сделайте больше 1 байта, чтобы быстро не переполнился.
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Блин как всё просто оказывается.
Спасибо большое!!!!!!
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Сообщение service47 »

Почему не работает код в обработчике прерывания, отслеживающий одновременное нажатие двух кнопок и удержание их в течении 2 сек., код одинаков для обоих обработчиков INT0 и INT1:

Код: Выделить всё

ISR(INT1_vect)
{
	_delay_ms(300);
      char i = 0;
	  while((PIND2 == 1) && (PIND3 == 1))
      {
	      _delay_ms(100);
	      i++;
	      if (i >= 20)
	      {
		      FLAG |= COUNTDOWN;
		      break;
	      }
      }	
}
Пробовал, вписывать вместо единицы ноль, но результата нет:
while((PIND2 == 0) && (PIND3 == 0))
Думаю, что дело в подтягивающих резисторах МК, так ли это?

Принципиальная схема, ключи S4, S5:
Изображение

Даташит на ATmega88PA: http://www.atmel.com/images/doc2545.pdf
Ответить

Вернуться в «Периферия»