PCINT - Это сложно. Как сделать дооолгое нажатие =)

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

:shock:
Озаботился я придумать новую фишку, доселя невиданную и не испытаннуя. Почему так? Сколько не листал я форумов, как-то мало кто работал с этим прерыванием.
Тема, видимо, не изучена так хорошо как таймеры. Какова преследуемая цель?
Цель: Распознать нажатие одной из трех кнопок в прерывании ISR(PCINT0_vect), ну и как то это обработать в основной программе...
Например зажечь светодиод по короткому нажатию а погасить по очень долгому :)
Но сколько не бился - проблема зависла. МК не может распознать долгое и очень долгое нажатие. Хотя вот с коротким все же вышло замечательно.
Идея в чем...
Во первых: чтобы распознать нажатие на определенной кнопке нужно написать что-то вроде этого...
Спойлер

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

ISR(PCINT0_vect)
{

    if ((PINB & 0x04)==0x00)
  
	{
    	      
	     flag_button_minus = 1;
	
	}
	
	 	if ((PINB & 0x02)==0x00)
	{
	
	     flag_button_plus = 1;
	  		
	}
    
    if ((PINB & 0x01)==0x00)
	{
		
		 flag_button_start_stop = 1;
		 	 
	}
И после выполнения задачи скидываем флаги
Спойлер

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

		
                        flag_button_minus = 0;
		        flag_button_plus = 0;
		        flag_button_start_stop = 0;
Во вторых где-то обработать. Я придумал такой код:
Показан пример для одной из кнопок...
Спойлер

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

void get_button_set()             
{
	

	if (((PINB & 0x04)==0x00) && (flag_quick == 1)) 
	{
	   
	    // Выполняем что-то 
		flag_quick = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_average == 1))
	{
		// Выполняем что-то еще
	 
		flag_quick = 0, flag_average = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_long == 1))
	{
		
		// Выполняем и убегаем =)
		flag_quick = 0, flag_average = 0, flag_long = 0;  
	}
}
И мой вариант отсчета паузы
Спойлер

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

   
    if (( flag_button_minus == 1 ) || ( flag_button_plus == 1 ) || ( flag_button_start_stop == 1 ))
    {
	    ms10++;
	  
	  if (ms10 > 10)
	  {
		  flag_quick = 1;
		  
		  ms2700++;
		  if (ms2700>2700)
		  {
			  flag_average = 1;
			  
			  ms5000++;
			  if (ms5000 >5000)
			  {
				  flag_long = 1;
			  }
		  }
		  
	   } 
	}
:sleep: Полный код приложу в архиве, ниже. Это пример применения кода на рабочем коде от счетчика. Индикатор общий анод.
Очень не понятна ситуация с отсчетом времени. Куда его не суй - он не работает. Пробовал и в прерывание и в таймерную часть сувать(глючит все конечно же), и в функцию пробовал спрятать. И как дальше быть? Может и не должно так работать, как я хочу. :shock:

P.S.
Нашел еще один глюк. После включения устройства нужно сделать 5-6 нажатий на кнопку, прежде чем она начнет работать хорошо :(
------
8:37 утра...
debounce
Я нарыл новую инфу. От дребезга избавляются тут... http://www.avrfreaks.net/forum/pin-chan ... debouncing
Посмотрю, может переиграю :)

Между прочим я тоже пробовал работать через PCIFR=0;
Это все фуфло, ибо этот флаг встает колом. С этими аппаратными флагами вечно одни глюки. :twisted:
Конечно, читая эту статью, мне приходили разные мысли. Подразумевается, что это прерывание выдаёт сигнал как по фронту, так и по спаду. Когда я это заметил, после первой зашивки, думал что кондер поможет. Я пока не готов использовать хаки. Пока меня такое поведение МК еще не совсем добило :)))

Мда. Мужик тоже согласен что дальнейшая обработка должна быть в главном цикле... "i totally agree with you all, the button test procedure should stay in the main!"
Я ощутил всю красоту тормозов всунув ПП прерывания легкую обработку. (мысли вслух)
Не, то что там советуют не для таких как я. Мы пойдем туда, где есть мёд. Мед есть там, где есть пчелы...
Вложения
timerv5stdo4.rar
(21.13 КБ) 150 скачиваний
Реклама
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Ну что же. Кое какой путь я все же нашел :)))
Мне удалось убить двух зайцев одним выстрелом.
Во первых: Я победил дребезг и никаких задержек не надо!
Во вторых: Я победил "второе нажатие" (срабатывание по спаду)
Заценяйте.
Спойлер

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


#define F_CPU 8000000UL

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


short unsigned int k = 0, ou = 0; 


char alarm_flag = 1, start_stop_flag = 1;						
long int h = 0, m = 30, s = 3,seconds_to_go = 0;

int ms2700=0, ms5000=0;

volatile unsigned char flag_button_plus = 0,flag_button_minus = 0, flag_button_start_stop = 0;
unsigned short int flag_quick = 0, flag_average = 0, flag_long = 0;  

const unsigned char codes[10]={0x14,0xD7,0x4C,0x45,0x87,0x25,0x24,0x57,0x4,0x5}; // 0-1-2-3-4-5-6-7-8-9
unsigned char counter[4]={0x08,0x04,0x02,0x01};  
unsigned char data[4]={0x14,0x14,0x14,0x14};  //    Err_t {0x2C,0xEE,0xEE,0xAC}


ISR(TIMER0_OVF_vect) 
{
    TCNT0 = 0x83;     
    
	PORTC=0x0f; 
	(k == 3) ? k = 0 : k++; 
	PORTC = counter[k];     
	PORTD = data[k];      
    
}

ISR(PCINT0_vect)
{
    if  (ou==9)  
	{
	    if ((PINB & 0x04)==0x00)
  
	    {
    	      
	     flag_button_minus = 1;
	
    	}
	
	 	if ((PINB & 0x02)==0x00)
	    {
	
	     flag_button_plus = 1;
	  		
    	}
      
        if ((PINB & 0x01)==0x00)
	    {
		
		 flag_button_start_stop = 1;
		 	 
	    }
    
	}
	else
    {
	    (ou = 10);
    }
    
}


void get_button_set()             
{
	

	if (((PINB & 0x04)==0x00) && (flag_quick == 1)) 
	{
	    m++;
	    // Выполняем что-то 
		flag_quick = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_average == 1))
	{
		// Выполняем что-то еще
	    h=h+3;
		flag_quick = 0, flag_average = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_long == 1))
	{
		h=h+5;
		// Выполняем и убегаем =)
		flag_quick = 0, flag_average = 0, flag_long = 0;  
	}
}


void indicate()
{
	
	seconds_to_go = (((h*60)+m)*60)+s;
	h = seconds_to_go / (60*60);
	m =(seconds_to_go-(h*60*60))/60;
	s = seconds_to_go % 60;
	if (h==0)
	{

		data[0]=codes[m/10];
		data[1]=codes[m%10];
		data[2]=codes[s/10];
		data[3]=codes[s%10];
	}
	else
	{
		data[0]=codes[h/10];
		data[1]=codes[h%10];
		data[2]=codes[m/10];
		data[3]=codes[m%10];
	}
}

//**********************************************************************************************************************************
                                               //    Функции иницаализации программы   //

void init_timer (void) 
{
	
	TIMSK0 = (1<<TOIE0);
	TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00) ; //8.000.000/64 = 125.000 ????? ? ???. (0-1-1 - ???????? ?? 64)
	
}

void init_buttons (void) 
{

	DDRB &=~ ((1 << 0)|(1 << 1)|(1 << 2));  // Очистка битов направления
	PORTB |= (1 << PB0); //PB0 включен pull-up
	PORTB |= (1 << PB1); //PB1 включен pull-up
	PORTB |= (1 << PB2); //PB2 включен pull-up
// Подключаем кнопки одним концом на землю, другим на порт и через резистор
// 10к на 5в 
// Поскольку подключ. подтяг. резисторы, кнопки считаются нажатыми,
// если на ножке МК низкий уровень
}

void init_PCINT_interrups(void) 
{
	PCICR |= (1 << PCIE0); 
	PCMSK0 |= (1 << PCINT0)|(1<<PCINT1)|(1<<PCINT2);
}
//**********************************************************************************************************************************
                                              //        Главный цикл программы        //	


int main (void)
{
	cli();

	DDRC = 0x0f;    // PortC - anode           
	DDRD = 0xff;    // PortD - data 
	PORTD = 0;

	init_timer ();             //  таймер счетчик 0
	init_buttons();            //  кнопки
	init_PCINT_interrups();    //  прерывания

	
	sei ();                   
	
//**********************************************************************************************************************************
                                              //        Главный цикл программы        //	
	
	while(1)          
	{
      
	  if (( flag_button_minus == 1 ) || ( flag_button_plus == 1 ) || ( flag_button_start_stop == 1 ))
      {
           ms5000++; // Эта собака не работает
	   ms2700++; // Это соответсятвенно тоже

	       flag_quick = 1;

		   if (ms2700>2700)
		   {
 		      flag_average = 1;
			  
			  if (ms5000 >5000)
			  {
			      flag_long = 1;
			  }
		   }
		  
	  } 
	 

// более они не нужны
flag_button_minus = 0;
flag_button_plus = 0;
flag_button_start_stop = 0;



		get_button_set();
		indicate();
			
		
	

	} //while 
	return 0;
}
Но вопрос о долгом нажатии еще висит. Как-то надо задействовать эти две переменных ms5000, ms2700 =(
Есть правдо аж две идеи :P ...
Жаль правда, никто не критикует...

Еще я нашел одну нехорошую тенденцию ...
Когда я отнимаю слишком много (слишком много раз нажимаю на кнопку), ведь вместо m++ я поставил m--, и наш счет выходит из диапазона - доходит до 00:00 и идет дальше, на дисплей выводится бурден-морден. Как этот бурден ограничить? :o
Последний раз редактировалось krokodandi Вс июл 19, 2015 03:05:42, всего редактировалось 1 раз.
Реклама
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Не ужель только я знаю ответы на свои вопросы? :(
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Попробовал swich case, теперь среднее и длинное нажатие срабатывает не каждый раз.
Спойлер

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

#define F_CPU 8000000UL

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


short unsigned int k = 0, ou = 0; 


char alarm_flag = 1, start_stop_flag = 1;						
long int h = 0, m = 30, s = 3,seconds_to_go = 0;

int ms2700=0, ms5000=0;

volatile char flag_button_plus = 0,flag_button_minus = 0, flag_button_start_stop = 0;
unsigned short int flag_quick = 0, flag_average = 0, flag_long = 0;  
volatile short int flag_27 = 0, flag_50 = 0, enable_count_in_timer = 1; 

const unsigned char codes[10]={0x14,0xD7,0x4C,0x45,0x87,0x25,0x24,0x57,0x4,0x5}; // 0-1-2-3-4-5-6-7-8-9
unsigned char counter[4]={0x08,0x04,0x02,0x01};  
unsigned char data[4]={0x14,0x14,0x14,0x14};  //    Err_t {0x2C,0xEE,0xEE,0xAC}


ISR(TIMER0_OVF_vect) 
{
    TCNT0 = 0x83;     
    
	PORTC=0x0f; 
	(k == 3) ? k = 0 : k++; 
	PORTC = counter[k];     
	PORTD = data[k];      
    
  if (enable_count_in_timer == 0)
  { 
    (ms5000 == 5001) ? ms5000 = 0 : ms5000++;
    switch(ms5000)
	{
    case 2700:{flag_27 = 1; enable_count_in_timer = 0;	break;}
    case 5000:{flag_50 = 1; enable_count_in_timer = 0;	break;}
	}
  }
    
}

ISR(PCINT0_vect)
{
    if (ou%4==0) // (ou==9)  //
	{
	    if ((PINB & 0x04)==0x00)
  
	    {
    	      
	     flag_button_minus = 1;
	
    	}
	
	 	if ((PINB & 0x02)==0x00)
	    {
	
	     flag_button_plus = 1;
	  		
    	}
      
        if ((PINB & 0x01)==0x00)
	    {
		
		 flag_button_start_stop = 1;
		 	 
	    }
    
	}
	else
    {
	    (ou == 10) ? ou = 0 : ou++; 
	}
    
}


void get_button_set()             
{
	

	if (((PINB & 0x04)==0x00) && (flag_quick == 1)) 
	{
	    m--;
	    // Âûïîëíÿåì ÷òî-òî 
		flag_quick = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_average == 1))
	{
		h=h-3;
		// Âûïîëíÿåì è îòíèìàåì
	    flag_quick = 0, flag_average = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_long == 1))
	{
		h=h-5;
		// Âûïîëíÿåì è îòíèìàåì åùå áîëüøå =)
		flag_quick = 0, flag_average = 0, flag_long = 0;  
	}
//-------------------------------------------------------
	if (((PINB & 0x02)==0x00) && (flag_quick == 1)) 
	{
	    m++;
	    // Âûïîëíÿåì ÷òî-òî 
		flag_quick = 0;
	}
	else if (((PINB & 0x02)==0x00) && (flag_average == 1))
	{
		h=h+3;
		// Âûïîëíÿåì è ïðèáàâëÿåì
	    flag_quick = 0, flag_average = 0;
	}
	else if (((PINB & 0x02)==0x00) && (flag_long == 1))
	{
		h=h+5;
		// Âûïîëíÿåì è ïðèáàâëÿåì åùå áîëüøå =)
		flag_quick = 0, flag_average = 0, flag_long = 0;  
	}
//------------------------------------------------------
	if (((PINB & 0x01)==0x00) && (flag_quick == 1)) 
	{
	    // wack_up!
	    // ß íå ñïëþ... &)
		flag_quick = 0;
	}
	else if (((PINB & 0x01)==0x00) && (flag_average == 1))
	{
		// Select!
		// Âûáèðàåì ÷òî-òî èëè âõîäèì â ìåíþõó
	    flag_quick = 0, flag_average = 0;
	}
	else if (((PINB & 0x01)==0x00) && (flag_long == 1))
	{
	    // I want to Sleeeeeeep.=(
		// Âûïîëíÿåì è çàñûâàåì =)
		flag_quick = 0, flag_average = 0, flag_long = 0;  
	}


}


void indicate()
{
	
	seconds_to_go = (((h*60)+m)*60)+s;
	h = seconds_to_go / (60*60);
	m =(seconds_to_go-(h*60*60))/60;
	s = seconds_to_go % 60;
	if (h==0)
	{

		data[0]=codes[m/10];
		data[1]=codes[m%10];
		data[2]=codes[s/10];
		data[3]=codes[s%10];
	}
	else
	{
		data[0]=codes[h/10];
		data[1]=codes[h%10];
		data[2]=codes[m/10];
		data[3]=codes[m%10];
	}
}

//**********************************************************************************************************************************
                                               //    Ôóíêöèè èíèöààëèçàöèè ïðîãðàììû   //

void init_timer (void) 
{
	
	TIMSK0 = (1<<TOIE0);
	TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);
	
}

void init_buttons (void) 
{

	DDRB &=~ ((1 << 0)|(1 << 1)|(1 << 2));  // Î÷èñòêà áèòîâ íàïðàâëåíèÿ
	PORTB |= (1 << PB0); //PB0 âêëþ÷åí pull-up
	PORTB |= (1 << PB1); //PB1 âêëþ÷åí pull-up
	PORTB |= (1 << PB2); //PB2 âêëþ÷åí pull-up
// Ïîäêëþ÷àåì êíîïêè îäíèì êîíöîì íà çåìëþ, äðóãèì íà ïîðò è ÷åðåç ðåçèñòîð
// 10ê íà 5â 
// Ïîñêîëüêó ïîäêëþ÷. ïîäòÿã. ðåçèñòîðû, êíîïêè ñ÷èòàþòñÿ íàæàòûìè,
// åñëè íà íîæêå ÌÊ íèçêèé óðîâåíü
}

void init_PCINT_interrups(void) 
{
	PCICR |= (1 << PCIE0); 
	PCMSK0 |= (1 << PCINT0)|(1<<PCINT1)|(1<<PCINT2);
}
//**********************************************************************************************************************************
                                              //        Ãëàâíûé öèêë ïðîãðàììû        //	


int main (void)
{
	cli();

	DDRC = 0x0f;    // PortC - anode           
	DDRD = 0xff;    // PortD - data 
	PORTD = 0;

	init_timer ();             //  òàéìåð ñ÷åò÷èê 0
	init_buttons();            //  êíîïêè
	init_PCINT_interrups();    //  ïðåðûâàíèÿ

	
	sei ();                   
	
//**********************************************************************************************************************************
                                              //        Ãëàâíûé öèêë ïðîãðàììû        //	
	
	while(1)          
	{
      
	  if (( flag_button_minus == 1 ) || ( flag_button_plus == 1 ) || ( flag_button_start_stop == 1 ))
      {
         enable_count_in_timer = 0;
         flag_quick = 1;
		 
           if (flag_27 == 1)
		   {
 		      flag_average = 1;
			  flag_27 = 0;
		   }  
		   else if ( flag_50 == 1)
		   {
			      flag_long = 1;
				  flag_50 = 0;
		   }
		   
		  
	  } 
	 

// áîëåå îíè íå íóæíû
flag_button_minus = 0;
flag_button_plus = 0;
flag_button_start_stop = 0;



		get_button_set();
		indicate();
			
		
	

	} //while 
	return 0;
}
Русский опять кракозябрами :)) Править не буду и так понятно Ну а если нет, пишите. Поправлю...
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

во-первых, если вы не нашли ничего по этой теме, то это вовсе не значит, что никто ничего по этой теме не знает. просто для тех, кто принципиально разобрался с прерываниями и кнопками уже нет проблемы с PCINT и долгим нажатием...
во-вторых, вы немного усложняете все.

обозначьте пины, к которым подключены ваши кнопки

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

#define KEY1 _BV(PC0)
#define KEY2 _BV(PC1)
// и так далее
#define ALL_KEY (KEY1 | KEY2 | .... | NEYN)
в прерывании просто сохраняйте значение порта, к которому подключены кнопки. так как PCINT срабатывает и по переднему и по заднему фронту сигнала (по изменению уровня), то в вашей переменной всегда будет активное состояние кнопок

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

volatile uint8_t keys;

ISR(PCINT0_vect){
   keys = ~PINC & ALL_KEY;
}
так как обычно кнопки вешают с пина на землю, нажатому состоянию кнопки будет соответствовать 0 на пине, поэтому желательно инвертировать состояние пинов, чтобы далее в программе уже использовать единичку, как признак нажатия кнопки

так как может возникать дребезг, необходимо его подавить. для этого нужно дважды опрашивать состояние кнопок, делая паузу между этими опросами. можно делать это в обработчике прерывания таймера, срабатывающем каждые 10-20 миллисекунд. но вполне можно делать это и при помощи тупой задержки. если дважды вы считали одно и то же состояние кнопок - это и есть истинное их состояние (если вы используете таймер, можно не сравнивать отсчеты).

итак, вы будете иметь текущее состояние кнопок. в нужном месте вы можете обрабатывать кнопки при помощи switch

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

switch(keys){
case KEY1: // нажата первая кнопка
                break;
case KEY1 | KEY2: // нажаты обе кнопки 1 и 2
                break;
default:
              // ничего не нажато или комбинация запретная
                break;
}
как определить, долго ли нажата кнопка? да очень просто! завести переменную-флаг, проверять этот флаг в обработчике нужной кнопки, если флаг уже установлен - проверять истекшее с момента установки флага время и, когда долгое время истечет, что-то делать, а если флаг еще не установлен - устанавдивать его и начинать отсчет времени. в секции default этот флаг сбрасывать.

вот и все.

разумеется, отсчет интервалов проще всего делать при помощи таймера. например, я обычно делаю как-то так

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

volatile uint8_t tens_ms_wait = 0;

ISR(TIMER0_OVF_vect){
   // срабатывает каждые 10 мс
   if(tens_ms_wait) tens_ms_wait--;
}

static uint8_t key1_pressed; // это флаг, о котором говорил ранее

// вот так я бы обрабатывал удержание нажатой кнопки KEY1 в течение 500 мс

case KEY1:
    if(key1_pressed){
        if(!tens_ms_wait){
           // тут уже пора отрабатывать долгое нажатие кнопки
        } 
    } else {
        key1_pressed = KEY1; // установили флаг
        tens_ms_wait = 50; // включили задержку в 500 мс
        // тут можно отработать начало нажатия кнопки
    }
как-то так...

ну, пока я писал, вы уже примерно в том направении и двинулись, но все равно несколько путано у вас...

P.S. да, кстати: если вы не собираетесь МГНОВЕННО реагировать на нажатие кнопки, то вам вообще не нужно использовать PCINT - просто в таймере каждые 10 мс опрашивайте PINC и далее по тексту...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Я попробую переписать как-то так... Сложновато для меня отработать обработку. Вроде логично поступаю, но работает как-то все не так как хочу.
Всего-то надо три вида задержки размазать по трем кнопкам. С другой стороны, могло быть и больше. :)
Вопрос тогда в универсальности.
Что же, буду пробовать. Пока я верного и проверенного варианта не вижу.
Спасибо.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я вам верный и проверенный АЛГОРИТМ на примере одной кнопки описал. если нужно отрабатывать разные кнопки, то вместо флага лучше всего запоминать имено состояние кнопок ДО switch, и там же ДО него включать таймер. а вот уже в switch-е обрабатывать каждую кнопку.

в общем, направление у вас пока верное, а то, что не получается - это от небольшого опыта. разберетесь, думаю...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

ARV писал(а):я вам верный и проверенный АЛГОРИТМ на примере одной кнопки описал. если нужно отрабатывать разные кнопки, то вместо флага лучше всего запоминать имено состояние кнопок ДО switch, и там же ДО него включать таймер. а вот уже в switch-е обрабатывать каждую кнопку.

в общем, направление у вас пока верное, а то, что не получается - это от небольшого опыта. разберетесь, думаю...
:) Думаю тоже так Я
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

krokodandi писал(а): :) Думаю тоже так Я
мастер Yoda? :shock: :shock: :shock:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

ARV писал(а):
krokodandi писал(а): :) Думаю тоже так Я
мастер Yoda? :shock: :shock: :shock:

Иногда говорю, как зеленый. Принято так иногда. :))) Самому смешно бывает.
Жаль не такой мудрый, да и опыта бы набраться. Но есть стремленье. Думаю, не плохо это. 8)
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Занятно получается, если в таймере счетчике прописать вместо другой переменной "s"
Сразу вместо минут начинают бежать сотки. Прям зрелище, хлеба не хватает. :)))
Зато понимаешь, что кусок кода работает отлично.

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

  if (enable_count_in_timer == 0)
  { 
    (s == 5001) ? s = 0 : s++;   //ms5000++;
    switch(s)
	{
    case 2700:{flag_27 = 1; enable_count_in_timer = 0;	break;}
    case 5000:{flag_50 = 1; enable_count_in_timer = 0;	break;}
	}
  }
    
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Чуть выше я описал кусок кода. Не понимаю, почему case не выполняется? Вроде написал case 2700, но все, что в нем не выполняется! Почему так происходит?

можно написать и так

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

ISR(TIMER0_OVF_vect) 
{
    TCNT0 = 0x83;     
    
	PORTC=0x0f; 
	(k == 3) ? k = 0 : k++; 
	PORTC = counter[k];     
	PORTD = data[k];      
    
  if (enable_count_in_timer == 0)
  { //s = 0;
    //(i == 5000) ? i = 0 : i++;   //ms5000++;
    if (++s > 5000)
	{
	switch(s)
	   {
       case 2700:{flag_27 = 1; /*s++;*/ ;enable_count_in_timer = 1;	break;}
       case 5000:{flag_50 = 1; /*s=s+10;*/ ;enable_count_in_timer = 1;	break;}
	   }
     }
  }
    
}
Как написать. Считай до 2700 и выполняй если 2700
и тоже самое до 5000 ?
Может я уже глючу? А может чего-то забыл?
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Нусс... Утром устал, ушел спать. Вечером проснулся и опять работать. :)
Буду думать уже на свежую голову и следовать саветам дальше.
Прям бэк то ЮССАР, назад в страну советов
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Мне не понятно одно.
Совет был про #define

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

ALL_KEY (KEY0 | KEY1 | KEY2)
Поправил на

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

#define KEY0 _BV(1<<PINB0)
#define KEY1 _BV(1<<PINB1)
#define KEY2 _BV(1<<PINB2)
#define ALL_KEY (KEY0 || KEY1 || KEY2)
Далее написал в прерываниях таймера

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

    
        ms2700++;
	ms5000++;
       		  
	if ((ALL_KEY == 1) && (ms2700 == 2700))
    {
	  ms2700 = 0; flag_average = 1;s--;
	  
	  if ((ALL_KEY == 1) && (ms5000 == 5000))
	  {
	   ms5000 = 0; flag_long = 1;
	  }
	 
	 else if (ms2700 == 2700)
	 {
	   ms2700=0;
	 }
	 else if (ms5000 == 5000)
	 {
	  ms5000=0;
	 }  
А у меня идут автоматические срабатывания, сначала после 5ти секунд, потом после 8, потом после 3х. Как видно у меня выполняется s-- после задержки в 2700
Это все из-за ALL_KEY. Он как будто не работает...
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

НУ а если подставить вместо ALL_KEY переменную, процесс вовсе затыкается. Клавиша не реагирует на нажатия :(
Хотя нет, опять ложные срабатывания. МК живет своей жизнью. Ему даже кнопки не нужны :shock:
Спойлер

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

#define F_CPU 8000000UL
#define KEY0 _BV(1<<PINB0)
#define KEY1 _BV(1<<PINB1)
#define KEY2 _BV(1<<PINB2)
#define ALL_KEY (KEY0 || KEY1 || KEY2)

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


short unsigned int k = 0, ou = 0; 


char alarm_flag = 1, start_stop_flag = 1;						
long int h = 0, m = 1, s = 3,seconds_to_go = 0;

int ms2700=0, ms5000=0;

volatile char flag_button_plus = 0,flag_button_minus = 0, flag_button_start_stop = 0;
unsigned short int flag_quick = 0, flag_average = 0, flag_long = 0;  
volatile short int flag_27 = 0, flag_50 = 0;

volatile short int buTon_SuperPush = 1; 

const unsigned char codes[10]={0x14,0xD7,0x4C,0x45,0x87,0x25,0x24,0x57,0x4,0x5}; // 0-1-2-3-4-5-6-7-8-9
unsigned char counter[4]={0x08,0x04,0x02,0x01};  
unsigned char data[4]={0x14,0x14,0x14,0x14};  //    Err_t {0x2C,0xEE,0xEE,0xAC}


ISR(TIMER0_OVF_vect) 
{
    TCNT0 = 0x83;     
    
	PORTC=0x0f; 
	(k == 3) ? k = 0 : k++; 
	PORTC = counter[k];     
	PORTD = data[k];      
    
    ms2700++;
	ms5000++;
       		  
	if ((buTon_SuperPush == 0) && (ms2700 == 2700))
    {
	  ms2700 = 0; flag_average = 1;s--; buTon_SuperPush = 0;
	  
	  if ((buTon_SuperPush == 0) && (ms5000 == 5000))
	  {
	   ms5000 = 0; flag_long = 1; buTon_SuperPush = 0;
	  }
	 
	 else if (ms2700 == 2700)
	 {
	   ms2700=0;
	 }
	 else if (ms5000 == 5000)
	 {
	  ms5000=0;
	 }  
	
	}
}

ISR(PCINT0_vect)
{
    if (ou==9) 
	{
	    if ((PINB & 0x04)==0x00)
  
	    {
    	      
	     flag_button_minus = 1;
	
    	}
	
	 	if ((PINB & 0x02)==0x00)
	    {
	
	     flag_button_plus = 1;
	  		
    	}
      
        if ((PINB & 0x01)==0x00)
	    {
		
		 flag_button_start_stop = 1;
		 	 
	    }
        

		 if (( flag_button_minus == 1 ) || ( flag_button_plus == 1 ) || ( flag_button_start_stop == 1 ))
      {
        buTon_SuperPush = 0;
      }   	   		   
	   
	}
	else
    {
	    (ou == 10);
    }
    
}


void get_button_set()             
{
	

	if ((PINB & 0x04)==0x00)// && (flag_quick == 1)) 
	{
	    
	   
		flag_quick = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_average == 1))
	{
		h=h-3;
		
	    //flag_quick = 0;
		flag_average = 0;
	}
	else if (((PINB & 0x04)==0x00) && (flag_long == 1))
	{
		h=h-5;
		
		//flag_quick = 0;
		//flag_average = 0;
		flag_long = 0;  
	}
//-------------------------------------------------------
	if ((PINB & 0x02)==0x00)// && (flag_quick == 1)) 
	{
	    s++;
	   
		flag_quick = 0;
	}
	else if (((PINB & 0x02)==0x00) && (flag_average == 1))
	{
		h=h+3;
		
	    //flag_quick = 0;
		flag_average = 0;
	}
	else if (((PINB & 0x02)==0x00) && (flag_long == 1))
	{
		h=h+5;
		
		//flag_quick = 0;
		//flag_average = 0;
		flag_long = 0;  
	}
//------------------------------------------------------
	if ((PINB & 0x01)==0x00)// && (flag_quick == 1)) 
	{
	    // wack_up!
	  
		flag_quick = 0;
	}
	else if (((PINB & 0x01)==0x00) && (flag_average == 1))
	{
		// Select!
		
	    //flag_quick = 0;
		flag_average = 0;
	}
	else if (((PINB & 0x01)==0x00) && (flag_long == 1))
	{
	    // I want to Sleeeeeeep.=(
		
		//flag_quick = 0;
		//flag_average = 0;
		flag_long = 0;  
	}


}


void indicate()
{
	
	seconds_to_go = (((h*60)+m)*60)+s;
	h = seconds_to_go / (60*60);
	m =(seconds_to_go-(h*60*60))/60;
	s = seconds_to_go % 60;
	if (h==0)
	{

		data[0]=codes[m/10];
		data[1]=codes[m%10];
		data[2]=codes[s/10];
		data[3]=codes[s%10];
	}
	else
	{
		data[0]=codes[h/10];
		data[1]=codes[h%10];
		data[2]=codes[m/10];
		data[3]=codes[m%10];
	}
}

//**********************************************************************************************************************************
                                              

void init_timer (void) 
{
	
	TIMSK0 = (1<<TOIE0);
	TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);
	
}

void init_buttons (void) 
{

	DDRB &=~ ((1 << 0)|(1 << 1)|(1 << 2));  
	PORTB |= (1 << PB0); //PB0 pull-up
	PORTB |= (1 << PB1); //PB1 pull-up
	PORTB |= (1 << PB2); //PB2 pull-up

}

void init_PCINT_interrups(void) 
{
	PCICR |= (1 << PCIE0); 
	PCMSK0 |= (1 << PCINT0)|(1<<PCINT1)|(1<<PCINT2);
}
//**********************************************************************************************************************************
                                            

int main (void)
{
	cli();

	DDRC = 0x0f;    // PortC - anode           
	DDRD = 0xff;    // PortD - data 
	PORTD = 0;

	init_timer ();            
	init_buttons();            
	init_PCINT_interrups();    

	
	sei ();                   
	
//**********************************************************************************************************************************
            
	
	while(1)          
	{



flag_button_minus = 0;
flag_button_plus = 0;
flag_button_start_stop = 0;



		get_button_set();
		indicate();
			
		
	

	} //while 
	return 0;
}
Наверное надо писать все заново.

Я так думаю, что все эти задержки, это какое-то болото. Видимо как и в случае с обработкой нажатия без задержек в ISR(PCINT0_vect), мне придется придумывать, что-то нестандартное. В ином случае я начну нервничать, а когда я нервничаю - хочу есть. Когда я ем - потею. Когда потею, я нервничаю. Так, что и время, и код тоже в помойку. :?
Последний раз редактировалось krokodandi Вс июл 19, 2015 03:06:49, всего редактировалось 1 раз.
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Все переработаю! Все заново! Потому, что это все - порнота...
Хоть я и новичок в программировании, но отлично усвоил, что использование различного рода задержек все-таки есть плохой тон.
Кусок переделан за последние 3 часа и без всяких задержек. :beer: Ушел на работу :P
:kill:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

krokodandi писал(а):НУ а если подставить вместо ALL_KEY переменную, процесс вовсе затыкается. Клавиша не реагирует на нажатия :(
Хотя нет, опять ложные срабатывания. МК живет своей жизнью. Ему даже кнопки не нужны :shock:
болото - это ваш стиль программирования, вы в нем утонете однозначно.
во-первых, вы совершенно невнимательны. я вам показывал пример с макросами KEY1 и т.п. - вы его видели? вы внимательно на него смотрели? вы что у себя в коде написали? где я вам рекомендовал делать ЛОГИЧЕСКОЕ ИЛИ для этих макросов?

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

#define ALL_KEY (KEY1 | KEY2 | KEY3) // это я советовал
#define ALL_KEY (KEY1 || KEY2 || KEY3) // это вы накорябали
разумеется, ничего нормально работать не будет

во-вторых, вы (предполагаю) как и большинство начинающих считаете, что чтение учебников - это для лохов и слабаков, а крутые программисты всегда сами все делают, не читая книжек. а я настоятельно рекомендую вам почитать книги по языку Си, чтобы, как минимум, понимать, что делается в том или ином случае.
в частности, для чего я вам рекомендовал вводить макросы KEY1 и т.п.? уж наверное не для того, чтобы всюду по коду вы продолжали писать невнятные PINB & 0x01 - что за 0x01? почему 0x01? связано ли это с KEY1 или нет?
если вы вводите макрос, обозначающий КНОПКУ, то ВЕЗДЕ в коде, где по смыслу идет работа с ЭТОЙ КНОПКОЙ, вы ОБЯЗАНЫ использовать именно ЭТОТ МАКРОС, а не его эквивалент.

в-третьих, задержки - это отнюдь не зло. я сделал не один проект, и ни в одном не использовал прерывания для работы с кнопками. более того, я таймер использовал для работы с кнопками всего один раз. почти все мои проекты сделаны с использованием ПРОГРАММНЫХ ЗАДЕРЖЕК - и отлично себя показали. я даже сигналы пульта дистанционного управления принимаю кодом, основанном не на прерываниях, а на задержках! просто я понимаю, что делаю.

попробуйте разбить свою задачу на подзадачи и решать каждую отдельно - возможно, в этом случае у вас будет меньше проблем. не знаю, хорошо ли я описал принцип нисходящего программирования, но все равно порекомендую прочесть мою статью, надеюсь, это немного поможет вам в идеологии программирования. а при правильной идеологии вы и задержек бояться перестанете, и ошибок меньше будете допускать... порядок - он порядок и есть, и в коде, и в голове...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Электрический кот
Аватара пользователя
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Сообщение Mishany »

я уже тоже не одну собаку съел на кнопках, и пока остановился на ацп, там и короткое и дплинное и мгновенная реакция на нажатие и только при отпускании, места занимает 3 строчки в прерывинии от ацп, и свободная функция опроса кнопок по пару строчек на кнопку, и одна переменная char для 8 кнопок. пример могу только во вторник закинуть.
вопрос при переводе порта в режим PCIN подтяжка же не работает? порт в Z состояние переходит?
Открыл глаза
Сообщения: 47
Зарегистрирован: Ср ноя 12, 2014 14:48:39

Сообщение krokodandi »

Mishany писал(а):я уже тоже не одну собаку съел на кнопках, и пока остановился на ацп, там и короткое и дплинное и мгновенная реакция на нажатие и только при отпускании, места занимает 3 строчки в прерывинии от ацп, и свободная функция опроса кнопок по пару строчек на кнопку, и одна переменная char для 8 кнопок. пример могу только во вторник закинуть.
вопрос при переводе порта в режим PCIN подтяжка же не работает? порт в Z состояние переходит?
Я пока ацп не изучал. Да и про Z-состояние пока ответить ничего не могу.
На самом деле почему именно PCINT? Потому сразу любая кнопка, потому что никто не пишет особо про применение сразу кучи кнопок(это не частный случай). Зато у всех
какие-то баги вылезают. Мне интересно стало... Я разобрался и понял, что тут еще можно и схитрить. Задержки делаются за счет арифметики над главным циклом, потом непрерывный процесс счета... просто раскидываем полезную цикличную работу МК по задачам. не надо делать , бесконечные i++, вдобавок сделав один раз деление ложных срабатываний на содержимое простой переменной, изначально и в последующей работе забываем про эти ложные срабатывания. Это самое быстрое и элементарное, что мне как киповцу, пришло в голову. Моё дело не разработка решения в соответствии со строгим изложением в куче учебников и прочей полезной литературе, а поиск оригинальных решений, способных сократить время обработки задачи. Я не люблю придумывать замену унификациям (любая замена принятой норме эта костыль), это если говорить про логику или математику на бумаге. Просто если математику дать тоже самое, но только изложенное не математикой а русским изложением - он разберется, но пройдет время.
- Умную литературу я не отвергаю, но и мириться с тотальным однообразием не желаю.-
А вот эта мысль про решения различных задач стандартной компоновкой.
Это как раз я и не люблю, потому что в литературе задачи и решения их изложены для ознакомления в учебно-образовательных целях без каких либо незамысловатых вариаций.
Поэтому чаще всего там изложен тупой как молот, но действенные как он же, метод решения теоретической задачи.

Что касаемо (PINB & 0x02)==0x00... (0х02 - это значение в регистре PIN, зачит еденицу в PINX1) Я держу логику перед глазами всегда. И когда мне удается собираться и думать о программных блоках (си) как о логических законченных моделях(к примеру как о модели мультивибратора), все начинает получаться. Не могу понять, как можно такое выражение запихнуть в макрос, ведь потом начнешь путать его с изложением внутренней основной мысли. Мы с железками говорим по разному и мешать одно с другим, значит варить кашу и в голове и в общении с напарником.
Я так работать не могу ибо я привык делать все для дурака. Любой его вопрос должен быть моим молчанием. Так работать сложно, но можно.

А еще дико помогает образность мышлеия. Это когда перед глазами эти блоки тасуешь, Всегда возникает иной вариант, нежели был прежде.
Разбивать на подзадачи основную задачу полезно на ранних стадиях, позже когда работаешь с блоками, надо оглядывать 2-3 блока и разбирать их работу по входящим и исходящим значениям. И если требование универсальности и сходимости блоков нарушено, то один из блоков требует пересмотра алгоритма работы.
Иными словами, если ключ к гайке не подходит, ищем другой. Потому и существует выражение про "Умение гайки крутить" :)
Смысл в том, что ключ обычно кто-то берет и не возвращает, а там где он должен быть его нет. Приходит на помощь что? Смекалка.

Про то, что не одна программа таким образом писана... Могу тут тоже ответить. Привычка дело хорошее настолько, насколько и плохое. Поэтому привычка должна обновляться.
Ибо если за рулем будет всегда одна привычка, рано или поздно встретишь фуру. Это я как бывший гонщик могу совершенно железно утвердить.
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

krokodandi,Я остановился на таком реализации.
Преимущества:
1) Клавиши можно подключать хоть как и хоть куда (на основную работу с клавишами это не влияет).
2) Все задержки размазываются по итерациям.
http://www.kit-e.ru/articles/circuit/2007_08_170.php
Ответить

Вернуться в «AVR»