Skocz do zawartości

[C] Problem z obsługą przycisku w przerwaniu.


emilo9

Pomocna odpowiedź

Witam.

Mój problem jest następujący. Pomiar napięcia rozpoczynam przyciskiem i chcę go zakończyć tym samym przyciskiem. Najpierw sprawdzam czy wciśnięty jest przycisk i wykonuje się pomiar w trybie pomiaru ciągłego. Zakończenie pomiaru jest obsługiwane przerwaniem. Teraz problem jest taki że sprawdzenie ponownego wciśnięcia przycisku działa tylko w funkcji obsługującej przerwanie, a nie działa w pętli głównej programu, nawet wtedy gdy próbowałem ustawiać flagę w przerwaniu i sprawdzać w pętli głównej czy wciśnięty jest przycisk. Teraz:

1. Jeśli sprawdzam stan przycisku w funkcji obsługującej przerwanie pojawiają się opóźnienia, które są niemile widziane.

2. Nie wiem jak powrócić na początek pętli głównej po sprawdzeniu czy przycisk został wciśnięty drugi raz.

Z góry dziękuję za pomoc.

Oto kod:

volatile float adc;                   //zmienna do obliczenia napięcia
volatile char flaga;                                
ISR(ADC_vect)
{
adc=((ADC*VREF)/1024)*DZIELNIK;              
//spr_2_przycisk();								
if(!(PINB & 0x01))
{									//sprawdzenie
	_delay_ms(100);
	while(!(PINB & 0x01)){}			         //stanu
	ADCSRA=(0<<ADEN);
	LCD_CLEAR;  						// przycisku
	_delay_ms(10);      
	LCD_LOCATE(0,0);    				        //przy zakończeniu pomiaru
       lcd_puts("Koniec pomiaru");

	}
}
void main(void)
{
   char wynik[]="            ";
lcd_init();                                          // Funkcja inicjalizuje wyświetlacz
   /* Włącza wyświetlanie */
	LCD_DISPLAY(LCDDISPLAY);
       menu_tekst();
LCD_CLEAR;
LCD_LOCATE(0,0);
       /* Funkcja lcd_puts wysyła do 
       wyświetlacza ciąg  znaków */
       lcd_puts("Wcisnij przycisk");
       _delay_ms(500);
DDRB  = 0x00; 
PORTB = 0x07;

while(1)
{
	//sprawdzenie stanu przycisku
	if(!(PINB & 0x01)) 
	{
		_delay_ms(100);
		while(!(PINB & 0x01 )){}	//po wciśnięciu i puszczeniu początek pomiaru

		adc_wl();      //inicjalizacja przetwornika
		sei();			// globalna obsługa przerwań

		for(;;)
		{
		sprintf(wynik,"U=%1.2f [V]",adc);     //konwersja wyniku
		LCD_LOCATE(4,1);
		lcd_puts(wynik);						//wyświetlenie wyniku pomiaru
		_delay_ms(200);
		}
	}
	_delay_ms(100);
	if(!(PINB & 0x02))
	{
		_delay_ms(100);
		while(!(PINB & 0x02)){}
		LCD_CLEAR;
		LCD_LOCATE(0,0);
		lcd_puts("Wybrales 2   ");
		_delay_ms(200);
	}
	if(!(PINB & 0x04))
	{
		_delay_ms(100);
		while(!(PINB & 0x04)){}
		LCD_CLEAR;
		LCD_LOCATE(0,0);
		lcd_puts("Wybrales 3    ");
		_delay_ms(200);
	}
}
}
Link do komentarza
Share on other sites

Nie odpowiem na główny problem, ale rzucają mi się w oczy dwie rzeczy:

- inicjujesz niektóre rzeczy w pętli zamiast raz (ADC i sei()) - po co?

- kod w obsłudze przerwania jest wolny - używasz delay oraz wolnego dzielenia podczas, gdy dzielnikiem jest potęga dwójki, więc mógłbyś "dzielnik" przesunąć o 10 bitów (jeśli to typ całkowity) lub chociaż podzielić go raz przed pętlą główną (jeśli się nie zmienia, a na to wygląda)

Link do komentarza
Share on other sites

Na moje po inicjacji pomiaru wpadasz w pętlę nieskończoną która w kółko wyswietla wynik pomiaru pomimo 'że pomiar jest już zakończony przez przerwanie. Skan stanu przycisku jest sprawdzany w przerwaniu bo przerwania "wskakują" w tę pętlę ale program nigdy nie dojdzie do końca pętli głównej.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.