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

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

Получается и так и есть в протеусе, что при нажатии кнопки и не отпускании происходит прерывание по спадающему фронту (т.е. получается теоретически лог.0), порт настроен на вход DDRD=0x00; с подтягивающими резисторами PORTD=0xff; (которые если отключить то прерывание не будет работать) бит PUD в регистре MCUCR отключен, прерывания разрешены и глобально разрешены.
Пишу в обработчике прерываний:

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

ISR(INT1_vect)  //MINUS PIND3
{_delay_ms(200); 
if (PIND3 == 0) 
{s--;}
}
и в протеусе нет реакции на нажатие кнопки, т.е. на входе порта нет лог.0. но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата.
С другой стороны в коде Alex'a прописаны:

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

#define ACT_BUTT_LEV    0       // Активный уровень нажатых кнопок
т.е. мне туда прописывать эту тройку, но тогда дальше:

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

if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
не будет работать из-за этой тройки, срабатывающей всегда.

Задача стоит такая сделать отслеживание кнопок от таймера:
При нажатии любой кнопки происходит увеличение или уменьшении значения на индикаторе на 1 (это работает, но не на таймере, а на векторах прерываний),
При нажатии и удержании в течении 3сек. происходит запуск обратного отсчета (работает если отслеживать циклом while флаги в регистре EIFR).
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

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

но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата
А Вас не смущает, что Вы пин (т.б. 1 бит) сравниваете с числом 3 ? :)
Реклама
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

Новая концепция: записывать чтобы-там ни было на входе порта в переменную и работать уже с ней:
Только такое условие работает с каждой кнопкой по отдельности, а вместе они почему то конфликтуют.

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

int Knopka_Staroe, Knopka_Novoe;
int Knopka_Star2, Knopka_Nov2;


Knopka_Staroe = (PIND&=(1<<3));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
	_delay_ms(80);  // Пауза для подавления дребезга контактов.
	Knopka_Novoe = (PIND&=(1<<3));  //...считываем новое состояние кнопки.

	if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
		_delay_ms(80);  // Пауза для подавления дребезга контактов.
		s--;  
	}
}
		
// Knopka_Star2 = (PIND&=(1<<2));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
// if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
// {
// 	_delay_ms(80);  // Пауза для подавления дребезга контактов.
// 	Knopka_Nov2 = (PIND&=(1<<2));  //...считываем новое состояние кнопки.
// 
// 	if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
// 	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
// 		_delay_ms(80);  // Пауза для подавления дребезга контактов.
// 		s++;
// 	}
// }	
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Помогите опросить кнопку

Сообщение a_skr »

Аlex писал(а):
но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата
А Вас не смущает, что Вы пин (т.б. 1 бит) сравниваете с числом 3 ? :)
:shock: А если учесть, что PIND3 является просто числом 3...
#define PIND3 3
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: Помогите опросить кнопку

Сообщение zero648 »

Вот что прописано в файле m88def.inc:

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

.equ  PIND3      =3
.equ  PIND2      =2
да и вообще если прерывание наступило, зачем тогда в прерывании проверять кнопку, если и так понятно, что она нажата, можно смело выходить из прерывания, и уже в основном цикле проверять это нажатие еще несколько раз на антидребезг, отвыкайте от паузного антидребезга и забудьте слово пауза, есть другое слово - игнор.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

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

a_skr писал(а)::shock: А если учесть, что PIND3 является просто числом 3...
#define PIND3 3
В таком случае, я - балерина :)))
Это как же нужно себя не уважать, чтобы делать такие объявления ? :)))
Реклама
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

Это определение бита а НЕ ПОРТА, все правильно. PIND3 - константа, которую НАДО подставлять в сравнение вроде PORTD = (1<<PIND3). На этой концепции построено все.
PINB3=PINC3=PIND3=3 ведь все эти биты портов 3-и по счету!!! Разница в имени константы, указывающая на порт всего лишь для удобства.
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

Тут: http://www.fanatnauki.ru/index.php?opti ... &Itemid=64
пишут, что:
PORTD = 0b10000000; // Подключаем подтягивающий PULL-UP резистор к 7 пину порта D.
DDRD = 0b00000000; // Настроим порт D на ввод информации.
// Важна последовательность! Сперва подключаем PULL-UP резистор,
// и только потом настраиваем порт на ввод, иначе кнопка работать не будет.
даже это не помогло.

Вобщем в связи с новой концепцией посмотрите код вначале цикла while(1), почему конфликтуют обе кнопки, но ведь если по отдельности то работают. Второй блок кнопки закомментирован, прерывания отключены:
Спойлер

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

#define F_CPU 1000000UL

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>


#define COUNTDOWN 1

volatile char FLAG = 0;
volatile char s = 6; 	//Переменная цифры
volatile char a = 6;
volatile char b = 1;    //Начальный сброс флага
volatile char c = 6;
volatile char j = 6;    //Перескок через ШИМ
// массив знаков на индикатор
char digits[11] = {0b00111111, 0b00000110, 0b00011011, 0b00001111, 0b00100110, 0b00101101, 0b00111101, 0b00000111, 0b00111111, 0b00101111, 0b00101111}; // PORTC 0,1,2,3,4,5,6,7,8,9,x
char digita[11] = {0b00000000, 0b00000000, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000, 0b00000001, 0b00000001, 0b00000001}; // PORTB

/******************************************************************/
#define ACT_BUTT_LEV    0       // Активный уровень нажатых кнопок
#define ACT_BUTT_LEV_2    0
//---------------------
#define PORT_BUTT_1     PIND    // Порт кнопки №1
#define PIN_BUTT_1      2       // Номер бита порта кнопки №1
#define PORT_BUTT_2     PIND    // Порт кнопки №2
#define PIN_BUTT_2      3       // Номер бита порта кнопки №2
//---------------------
#define PORT_LED_1      PORTB   // Светики
#define DDR_LED_1       DDRB    //
#define PIN_LED_1       2       //
#define PORT_LED_2      PORTB   //
#define DDR_LED_2       DDRB    //
#define PIN_LED_2       7       //
/******************************************************************/
int Knopka_Staroe, Knopka_Novoe;
int Knopka_Star2, Knopka_Nov2;
/******************************************************************/
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};    // Объявляем структуру 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 для нашей кнопки и иним её.
/******************************************************************/

/******************************************************************/
ISR (TIMER1_OVF_vect) {	s=3;	//interrupt [TIM1_OVF] void timer1_ovf_isr(void){ //TIMER1_OVF_vect_num
	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)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
	mButt_1.down = 1;                                                   // Устанавливаем флаг down
	if((mButt_1.cur!=ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
	mButt_1.up = 1;                                                     // Устанавливаем флаг up
	mButt_1.prev=mButt_1.cur;                                       // Сохраняем текущее значение. Оно для следующего входа будет предыдущим

	mButt_2.cur = (PORT_BUTT_2&(1<<PIN_BUTT_2))!=0;                         // Считываем текущее значение вывода.
   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;
	}
//----------------------//
}
/******************************************************************/

ISR(INT1_vect)  //MINUS PIND3
{_delay_ms(200); 
if (PIND3 == 0) //(PIND3 <= 3) работает (PIND3 <= 2,95) (PIND3 == 3)
      {s--;}
}

ISR(INT0_vect)  //PLUS PIND2
{_delay_ms(200); 
if (PIND2 == 0) //(PIND2 == 2)(PIND2 >= 2,995) работает, а если (PIND2 >= 3) то не работает
      {s++;}
}

void shim_start()
{
	if (j==6)
	{goto jstop;
	}
//	ASSR=0x00;
//	// Установим биты COM1A1-COM1A0:0b10,означает сброс вывода канала A при сравнении Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode), for Fast PWM. page135
//	TCCR1A |= (1 << COM1A1)|(0 << COM1A0)|(0 << WGM11)|(1 << WGM10);
//	// Установим биты WGM13-10:0b0101, согласно таблице это будет режим - Fast PWM, 8-bit, где верхний предел счета задается битом ICR1. page136
//	TCCR1B |= (0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(0 << CS10);
//	// Битами CS12-10:0b100 задаем источник тактового сигнала для таймера МК, clkI/O/256 (From prescaler)=31250Hz. page137
//	TCNT1 = 0x00; // начальная установка счетчика
//	TIMSK1=0x00;
//	ICR1 = 0x20;  // задаем период ШИМ, здесь у нас число 255,
//	// по формуле  fPWM=fclk_I/O/N*(1+ICR1) вычисляем частоту ШИМ, она будет равна 8MHz/256(1+2)=10416Hz
// 	// для FR3706 надо 50000Hz, irlm0030 надо 16666Hz<
// 	OCR1A = 0x50; // начальный коэффициент заполнения ШИМ 0xC8=200, 0x50=1/3
	jstop:
	j=0;
}

int main(void)
{
		DDRC=0x3f;  //0b00111111 0-ввод 1-вывод
		PORTC=0x00; // 
		PORTD=0xff; // 0b11111111 PORTD=0xff; 
		DDRD=0x00; //0b00001100 DDRD=0x0C;
		
		DDRB=0xFF; //0b11000111 PB1(OC1A)-ШИМ DDRB=0xC7;
		PORTB=0x00; //PORTB=0x00;
	EICRA  =  (1<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);	// настройка срабатывания прерываний The falling edge of INT1 generates an interrupt request
	PCICR  |= (1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);// разрешение прерываний PCINT23...16
	PCMSK2=0b11000000; //разрешаем прерывание pcint23 pcint22
	EIMSK=0b00000000; //разрешаем прерывание int0 и int1 - кнопка EIMSK=0b11000011; 
	//MCUCR=0b00001111;// IVSEL, IVCE
	sei(); //Глобальное разрешение прерываний
		//Установка таймера0
	//TCCR0A |= (0 << COM1A1)|(0 << COM1A0)|(1 << WGM01)|(0 << WGM00); //биты COM Normal port operation, OC0A disconnected, WGM T/C in CTC mode
	//TCCR0B |= (0 << WGM02)|(0 << CS02)|(0 << CS01)|(1 << CS00); //биты CS fclk_I/O/1
	//TCNT0=0x00;
	//OCR0A=0x80;	
	//----------------------//
	//TCCR0A=0x00; //TCCR0=0x00;
//	TCCR0B=0x01; //TCCR0=0x00;
//	TCNT0=0x00;
	// Timer/Counter 1 initialization
	TCCR1A=0x00; //для Compare Output Mode, non-PWM COM1A1/COM1B1=0 COM1A0/COM1B0=0 Normal port operation, OC1A/OC1B disconnected.
	TCCR1B=0x01; //Waveform Generation Mode Bit Description WGM10-13=0 Normal //CS12-10=001 No prescaling
	TCNT1H=0x00;
	TCNT1L=0x00;
	ICR1H=0x00;
	ICR1L=0x00;
	//OCR1AH=0x00;
	//OCR1AL=0x00;
	OCR1BH=0x00; //OCR1B compared with the counter value (TCNT1)
	OCR1BL=0x00;
	// Timer/Counter 2 initialization
	//ASSR=0x00;
	//TCCR2=0x00; //TCCR2=0x00;
	//TCNT2=0x00;
	//OCR2=0x00; //OCR2=0x00;
	MCUCR=0x00;
	//TIMSK0=0x04; //TIMSK=0x04;
//	TIMSK1=0x04; //TIMSK=0x04; //OCIE1B=1
	//ACSR=0x80;
	//SFIOR=0x00;
	//----------------------//
	
    while(1)
    {		
Knopka_Staroe = (PIND&=(1<<3));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
	//_delay_ms(80);  // Пауза для подавления дребезга контактов.
	Knopka_Novoe = (PIND&=(1<<3));  //...считываем новое состояние кнопки.

	if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
		//_delay_ms(80);  // Пауза для подавления дребезга контактов.
		s--;  
	}
}
		
// Knopka_Star2 = (PIND&=(1<<2));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
// if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
// {
// 	//_delay_ms(80);  // Пауза для подавления дребезга контактов.
// 	Knopka_Nov2 = (PIND&=(1<<2));  //...считываем новое состояние кнопки.
// 
// 	if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
// 	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
// 		//_delay_ms(80);  // Пауза для подавления дребезга контактов.
// 		s++;
// 	}
// }		
		
		//if (PIND3 == 3) //(PIND3 == 3) работает если кнопка не нажата
    //{s=8;}
		//if (PIND2 == 2) //(PIND2 == 2) работает если кнопка не нажата
	//{s=8;}
		//----------------------//
		if(mButt_1.up){     // Если кнопка была нажата -> отжата
		mButt_1.up=0;                   // Сбрасываем флаг
		PORT_LED_1 ^=(1<<PIN_LED_1);    // Инвертируем светодиод №1
		s++;
		}
		//----------------------//
		if(mButt_1.down){   // Если кнопка была отжата -> нажата
		mButt_1.down=0;                 // Сбрасываем флаг
		PORT_LED_2 ^=(1<<PIN_LED_2);    // Инвертируем светодиод №2
		s++;
		}
		//----------------------//	
		//----------------------//
		if(mButt_2.up){     // Если кнопка была нажата -> отжата
		mButt_2.up=0;                   // Сбрасываем флаг
		PORT_LED_1 ^=(1<<PIN_LED_1);    // Инвертируем светодиод №1
		s--;
		}
		//----------------------//
		if(mButt_2.down){   // Если кнопка была отжата -> нажата
		mButt_2.down=0;                 // Сбрасываем флаг
		PORT_LED_2 ^=(1<<PIN_LED_2);    // Инвертируем светодиод №2
		s--;
		}
		//----------------------//	
        		start:
        		if (b == 1)
        		{s=5;
	        		FLAG &= ~ COUNTDOWN;
	        		b++;
        		}
        		
        		if (s > 9)
        		s--;
        		else if (s == 0)
        		s++;
        		if (FLAG == COUNTDOWN)
        		{
	        		//cli();
					char i = 0;
	        		while (s > -1)
	        		{
		        		if (s > -1)
		        		{
			        		a = 5;
			        		c = 5;
			        		if (FLAG != COUNTDOWN)
			        		{
				        		goto start;
			        		}
			        		PORTB |= _BV(PB6); // чтобы мигала точка на индикаторе
			        		_delay_ms(250);
			        		PORTB &= ~_BV(PB6);
			        		_delay_ms(250);
		        		}
		        		PORTC = digits[s];
		        		PORTB = digita[s];
		        		_delay_ms(500);
		        		PORTB &= ~_BV(PB7); //Красный светодиод
		        		_delay_ms(500);
		        		PORTB |= _BV(PB7);
		        		s--;
		        		if (s == 0)
		        		{
        					PORTC = digits[s];
        					PORTB = digita[s];							
							j=0;
							shim_start();
			        		PORTB &= ~_BV(PB2); //Зеленый светодиод
			        		_delay_ms(250);
			        		PORTB |= _BV(PB2);
			        		_delay_ms(250);
		        		}
						i++; 
							if (i>=10)
							{ICR1 = 0x00;
							OCR1A = 0x00;}
	        		}
	        		sei();
	        		FLAG &= ~ COUNTDOWN;
        		}
        		PORTC = digits[s];
        		PORTB = digita[s];

    }
}
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Помогите опросить кнопку

Сообщение a_skr »

// Важна последовательность! Сперва подключаем PULL-UP резистор,
// и только потом настраиваем порт на ввод, иначе кнопка работать не будет.
Чушь несусветная. И "настраивать на ввод" необязательно. Там по включению итак нули.
Knopka_Staroe = (PIND&=(1<<3)); // Записываем старое состояние кнопки в переменную Knopka_Staroe.
Зачем там &= ?
Где _BV(), где (1<<PBx), где (1<<3). Опишите задачу. Составьте алгоритм. Очень сложно читать код.
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

a_skr писал(а):
Knopka_Staroe = (PIND&=(1<<3)); // Записываем старое состояние кнопки в переменную Knopka_Staroe.
Зачем там &= ?
Где _BV(), где (1<<PBx), где (1<<3). Опишите задачу. Составьте алгоритм. Очень сложно читать код.
Как я понимаю (PIND&=(1<<3)) это чтение состояния третьего пина порта, в любом случае что-бы это ни-было функция в протеусе действительно считывает замыкание кнопки на землю и реагирует на это.

Задача уже писал, вот она:
При нажатии любой кнопки происходит увеличение или уменьшении значения на индикаторе на 1 (это работает, но не на таймере, а на векторах прерываний),
При нажатии и удержании обоих клавиш в течении 3сек. происходит запуск обратного отсчета (работает если отслеживать циклом while флаги в регистре EIFR).

Алгоритм:
1. Опрос кнопок
2. Замкнута 1якнопка goto3 else goto4
3. Увеличить значение на 1
4. Замкнута 2якнопка goto5 else goto6
5. Уменьшить значение на 1
6. Замкнуты обе кнопки и удерживаются в течении 3сек. goto7 else goto1
7. Запуск обратного отсчета

Остальной код работает. Постараюсь выкладывать код покомпактнее.
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Помогите опросить кнопку

Сообщение a_skr »

Как я понимаю (PIND&=(1<<3)) это чтение состояния третьего пина порта
Это не так. a = (PIND&=(1<<3)); соответствует следующему коду:

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

PIND = PIND & (1<<3); // - не имеет смысла, т.к. регистр PIND только на чтение
a = PIND; // - в "a" попадут все биты PIND
Правильные варианты:

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

a = PIND & (1<<3); // - в "a" будет или ноль или 8
a = PIND & (1<<3) ? 1 : 0; // - в "a" будет или ноль или 1
a = (PIND>>3) & 1; // - тоже самое, займет меньше кода
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

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

Alexeyslav писал(а):Это определение бита а НЕ ПОРТА, все правильно. PIND3 - константа, которую НАДО подставлять в сравнение вроде PORTD = (1<<PIND3)
Интересно, если это константа, зачем тогда в имени буква "D" ? Она (эта константа) как то привязана конкретно к этому порту ?
Глупое, на мой взгляд, имя для объявления константы-номера бита, малоинформативное. Я, например, увидев её, даже и не понял, что под ней может скрываться цифра 3. На первый взгляд, PIND3 - Это 3-ий пин порта D.
Где логика .... :roll:
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Помогите опросить кнопку

Сообщение a_skr »

Чисто гипотетически, вдруг выйдет контроллер, в котором какая-нибудь ножка PD8 будет адресоваться через бит 0 в регистре PINDH, и тогда логично объявить константы PIND8 и PD8, равные нулю... ;) а в порту C не будет ножки PC8, тогда константы PINC8 не будет и компилятор даст ошибку при ее использовании. ;)

PS. ну есть же контроллеры, в которых только порт B, например и не все 8 бит задействованы...
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

В таком коде срабатывает первое if когда кнопка не нажата, а при нажатии кнопки, т.е. замыкании ее на землю второй if не срабатывает.

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

Knopka_Staroe = PIND3;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
	_delay_ms(80);  // Пауза для подавления дребезга контактов.
	Knopka_Novoe = PIND3;  //...считываем новое состояние кнопки.

	if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
		_delay_ms(80);  // Пауза для подавления дребезга контактов.
		s--;
	}
}
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Помогите опросить кнопку

Сообщение a_skr »

В этом коде вообще НЕТ опроса кнопок. "PIND3" - это просто "3". Выше дал "Правильные варианты" опроса.
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

a_skr спасибо, заработали обе кнопки, только три раза через раз срабатывают.

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

Knopka_Staroe = PIND & (1<<3) ? 1 : 0;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
	_delay_ms(80);  // Пауза для подавления дребезга контактов.
	Knopka_Novoe = PIND & (1<<3) ? 1 : 0;  //...считываем новое состояние кнопки.

	if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
		_delay_ms(80);  // Пауза для подавления дребезга контактов.
		s--;
	}
}
	
Knopka_Star2 = PIND & (1<<2) ? 1 : 0;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
	_delay_ms(80);  // Пауза для подавления дребезга контактов.
	Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;  //...считываем новое состояние кнопки.

	if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
	{     // В этом случае падающий фронт сформирован и можно инвертировать пины.
		_delay_ms(80);  // Пауза для подавления дребезга контактов.
		s++;
	}
}	
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Помогите опросить кнопку

Сообщение service47 »

Данный код в цикле while(1); работает раз через три, как сделать чтобы если нажата одна кнопка срабатывала одна команда, если другая то соответственно другая и стабильно. Прерывания отключены. Может дело в дэлэях, может есть способ их не использовать...
Спойлер

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

			Knopka_Staroe = PIND & (1<<3) ? 1 : 0;
			if (Knopka_Staroe) //кнопка не нажата тогда if=1
			{
				_delay_ms(20);
				Knopka_Novoe = PIND & (1<<3) ? 1 : 0;
				Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;
				if(!Knopka_Novoe && Knopka_Nov2) //кнопка нажата и кнопка не нажата тогда if=1
				{
					PORTB |= _BV(PB6); //точка на индикаторе загорается
					_delay_ms(100);
					s--;
				}
				PORTB &= ~_BV(PB6); //точка на индикаторе гаснет
			}

			Knopka_Star2 = PIND & (1<<2) ? 1 : 0;
			if (Knopka_Star2)
			{
				_delay_ms(20);
				Knopka_Novoe = PIND & (1<<3) ? 1 : 0;
				Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;
				if(Knopka_Novoe && !Knopka_Nov2)
				{
					PORTB |= _BV(PB6); //точка на индикаторе загорается
					_delay_ms(100);
					s++;
				}
				PORTB &= ~_BV(PB6); //точка на индикаторе гаснет
			}
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Помогите опросить кнопку

Сообщение shads »

Ды не изобретай велосипед... вот пару вариантов, глянь, может что подойдет...
http://asis-kbr.ru/forum/viewtopic.php?f=13&t=173
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение Мikа »

Добрый день, Коты! Получилась такая тема: остались свободными 2 ножки МК, которые как раз INT0 и INT1. И мне как раз нужно сделать 2 кнопки. И вот я думаю, что легче для программы, подключить библиотеку нажатия кнопок, в которой ловится 0 на ноге, потом заданное количество раз перепроверяется и даёт на выходе разрешение на выполнение кода. Или использовать внешнее прерывание, допустим, по спадающему фронту на ножках?
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Помогите опросить кнопку

Сообщение shads »

Подключение через INT0 или INT1 оправдано только если надо выводить устройство из энергосберегающих режимов...
В других случаях лучше периодически (в прерывании) опрашивать линии кнопок.
Ответить

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