Опрос кнопок микроконтроллером
Re: Вопросы по С/С++ (СИ)
Ребят, подскажите, пожалуйста, как на си обработать одновременное нажатие двух кнопок
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
drac0Sha, так-же как и одну, только обрабатываем две
Вариант подключения кнопок
Уважаемые форумчане, подскажите какой вариант из предложенных наиболее удобный! И желательно бы хотелось услышать как плюсы так и минуса каждой схемы подключения!
- Engineer_Keen
- Друг Кота
- Сообщения: 3868
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Вариант подключения кнопок
1)
+проще обработка с точки зрения программы
+можно обрабатывать любую комбинацию одновременно нажатых кнопок
-нужно много ног для подключения
-для аппаратного антидребезга нужны RC-цепочки для каждой кнопки
2)
+всего одна нога контроллера
-немного сложнее обработка кнопок
-нажатие более одной кнопки может обработаться как нажатие другой кнопки
+проще обработка с точки зрения программы
+можно обрабатывать любую комбинацию одновременно нажатых кнопок
-нужно много ног для подключения
-для аппаратного антидребезга нужны RC-цепочки для каждой кнопки
2)
+всего одна нога контроллера
-немного сложнее обработка кнопок
-нажатие более одной кнопки может обработаться как нажатие другой кнопки
Re: Вариант подключения кнопок
Спасибо за оперативный ответ!
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Вариант подключения кнопок
Второй вариант можно использовать только если в МК есть АЦП
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Помогите опросить кнопку
или шим+аналоговый компаратор.Второй вариант можно использовать только если в МК есть АЦП
Re: Помогите опросить кнопку
Сильно не пинайте я только учусь помогите разобраться по чему отслеживания кнопки не происходит
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 ; конец программы
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 ; конец программы
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Помогите опросить кнопку
Все правильно сделано, считывается состояние, сейчас собрал проект если кнопка нажата-моргает портом B в протеусе. Если не нажата - не моргает. Возможно просто вы не видите этого в реале так как потому что нет задержки перед выключением порта
Попробуйте так проверить, так просто копируется состояние ноги RA2 в порт 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 ; конец программы
Re: Помогите опросить кнопку
Протеуса у меня нет. Попробовал ваш вариант в МК . Глуха как в танке ,а в моем варианте горят все порты В сразу как подашь питания. Может надо ка кто по другому биты конфигурации выставить ?
-
zzontt
- Открыл глаза
- Сообщения: 54
- Зарегистрирован: Чт дек 13, 2012 19:31:00
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Помогите опросить кнопку
День добрый, пытаюсь организовать опрос двух кнопок, взял пример из этого сообщения
и переделал под себя, но вот какая загвоздка, все работает если я организовываю опрос либо кнопки 1 либо кнопки 2, но когда пытаюсь сделать так что бы работал опрос 2х кнопок, то почему то программа реагирует только на нажатие кнопки 1, подскажите в чем может быть проблема, что надо исправить что бы была реакция на нажатие обоих кнопок. Код моей программы ниже.
Аlex писал(а):Ну чтож, коли пошла такая пьянка, подкину и я своих дровишек в костёрчик )
Раз тут собрались одни АВРщики, пришлось поставить CV и черкнуть на нём примерчик обработки кнопок. CV взял из-за генератора кода, т.к. не хочется лезть в даташит на совершенно незнакомые мне МК. В общем, за им генерируемый код меня не пинать
. Остальное, что касается моей писанины - обсуждаем, критикуем, закидываем помидорами, ....
![]()
В архиве проект + файл всеми любимого протеуса:
Программа хорошо комментирована, так что, думаю, вопросов не возникнет.
Если кому будет интересно, могу добавить обработку длинного нажатия.
и переделал под себя, но вот какая загвоздка, все работает если я организовываю опрос либо кнопки 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();
}
}
Не бейте за глупости, я только учусь)
Re: Помогите опросить кнопку
Не нашел записи в mButt_2.cur.
-
zzontt
- Открыл глаза
- Сообщения: 54
- Зарегистрирован: Чт дек 13, 2012 19:31:00
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Помогите опросить кнопку
Совесть писал(а):Не нашел записи в mButt_2.cur.
Действительно, был не внимателен пропустил строчку, вопрос закрыт.
Спасибо.
Не бейте за глупости, я только учусь)
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Кстати, для каждой кнопки не нужно объявлять свой тип, достаточно одного:
Код: Выделить всё
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};
-
zzontt
- Открыл глаза
- Сообщения: 54
- Зарегистрирован: Чт дек 13, 2012 19:31:00
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Помогите опросить кнопку
Спасибо, буду знать.Аlex писал(а):Кстати, для каждой кнопки не нужно объявлять свой тип, достаточно одного
Последний раз редактировалось Аlex Чт мар 21, 2013 09:30:26, всего редактировалось 1 раз.
Причина: -
Причина: -
Не бейте за глупости, я только учусь)
Re: Помогите опросить кнопку
Пытаюсь сделать обработку длительного нажатия кнопки. Делаю вот так вот
но тут получается что при нескольких коротких нажатий переменная timer доходит до 10 и устанавливается флаг как этого избежать ? И вообще в правильную сторону копаю?
Код: Выделить всё
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 и устанавливается флаг как этого избежать ? И вообще в правильную сторону копаю?
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Код: Выделить всё
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 байта, чтобы быстро не переполнился.
Re: Помогите опросить кнопку
Блин как всё просто оказывается.
Спасибо большое!!!!!!
Спасибо большое!!!!!!
Re: Мелкие вопросы по МК и ПЛИС.
Почему не работает код в обработчике прерывания, отслеживающий одновременное нажатие двух кнопок и удержание их в течении 2 сек., код одинаков для обоих обработчиков INT0 и INT1:
Пробовал, вписывать вместо единицы ноль, но результата нет:
while((PIND2 == 0) && (PIND3 == 0))
Думаю, что дело в подтягивающих резисторах МК, так ли это?
Принципиальная схема, ключи S4, S5:

Даташит на ATmega88PA: http://www.atmel.com/images/doc2545.pdf
Код: Выделить всё
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