logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega8][C] RC-5 po raz kolejny

siemman 05 Lis 2009 18:02 1877 6
REKLAMA
  • #1 7219682
    siemman
    Poziom 11  
    Witam.
    Wiem że tematów dotyczących RC-5 było już wiele, jednak nie chciałem używać gotowego programu, tylko samo coś napisać aby lepiej zrozumieć. Mój układ złożony jest z atmegi8 tsop1736 i wyświetlacza LCD, a jego zadaniem jest odebranie instrukcji z pilota i wyświetlenie jej na ekranie.
    Oto kod mojego programu:

    Nie potrafię zlokalizować gdzie zrobiłem błąd, program zawiesza się i cały czas czyści ekran i wyświetla liczbę 4. Oczywiście dzieje się tak dopiero po wciśnięciu przycisku na pilocie. Kody do obsługi wyświetlacza pochodzą z http://radzio.dxp.pl/hd44780/ .
    Prosiłbym o pomoc w zlokalizowaniu błędu.
  • REKLAMA
  • #2 7219868
    tmf
    VIP Zasłużony dla elektroda
    Zobacz jak dziala twoj program - po pierwszym impulsie z pilota jest on wyswietlany, a nastepnie poniewaz ciagle sa odblokowane przerwania cyklicznie jest wywolywane TIMER1_COMPA_vect - i tu juz nie ma znaczenia czy wciskasz pilota czy nie. Poza tym powinienes blokowac przerwania tego timera i je odblokowywac w przeznaczonym do tego rejestrze, a nie uzywac flagi przerwan globalnych. Wyswietlanie czegos w procedurze obslugi przerwania tez jest pomyslem raczej kiepskim (ta procedura powinna sie skonczyc jak najszybciej).
  • REKLAMA
  • #3 7220255
    siemman
    Poziom 11  
    Trochę przekształciłem mój kod, wg wskazówek

    Nadal nie działa.
    Może mój zamysł w ogóle jest zły.
    po otrzymaniu impulsu uC ma odczekać 0,45ms i jeżeli nadal na wejściu jest stan wysoki ma rozpocząć się próbkowanie, w tym celu timer ma odmierzać czas dokładnie 1,788ms czyli tyle ile trwa jeden jeden bit rozkazu,
    Wywołanie przerwania ma następować co 1,788ms czyli w przerwaniu odczytuje stan impulsu i zapisuje go w zmiennej przez dodanie 1 i przesunięcie bitowe o jedno miejsce w lewo. Jest to moje pierwsze spotkanie z timerem więc możliwe że robię coś źle właśnie w tym miejscu.
    Będę wdzięczny za każdą pomoc.
  • #4 7221057
    tmf
    VIP Zasłużony dla elektroda
    Bo ciagle nie zmieniles jednej rzeczy - pierwszy kod ci odblokowywuje przerwania i sa one odblokowane juz zawsze, nawet jesli nic nie nadajesz dalej to ta procedura zachowuje sie tak jakby byly nadawane kolejne znaki. Musisz po odebranu ostatniego znaku je ponownie blokowac. Podpowiem ci, ze: TIMSK |= (0 << OCIE1A); nie zeruje OCIE1A.
  • REKLAMA
  • #5 7223264
    siemman
    Poziom 11  
    Dziękuję jak na razie za wskazówki ale nadal nie udało mi się doprowadzić układu do działania. Przekształciłem kod, dorzuciłem obsługę odebrania impulsu jako przerwania INT1. i po uruchomieniu i wciśnięciu dowolnego przycisku na pilocie, na ekranie pojawia się 01111111111111 i tak za każdym razem.
    Oto kod:
  • REKLAMA
  • #6 7223663
    tmf
    VIP Zasłużony dla elektroda
    TIMSK ^= (1 << OCIE1A); - powoduje zmiane stanu pinu na przeciwny, jesli chcesz wyzerowac to stosuj TIMSK &=~ (1 << OCIE1A); a jesli ustawic to TIMSK |= (1 << OCIE1A);
    Nastepne - to, ze blokujesz przerwania od timera nie znaczy, ze timer w tym czasie nie liczy - w efekcie pierwsze przerwanie wcale nie nastepuje po 1778 cyklach timera tylko losowo. Podobnie prescaler - on sobie caly czas liczy.
  • #7 7225239
    siemman
    Poziom 11  
    Staram się stosować do wszystkich wytycznych ale cały czas nie działa, po wciśnięciu przycisku na pilocie, pojawia się to samo co wcześniej, dodałem jeszcze diodę na PD0 żeby sprawdzić ile razy wywołane jest przerwanie od INT i po jednorazowym wciśnięciu przycisku dioda gaśnie i znów się zapala. przy przytrzymaniu przez moment gaśnie i zapala się więcej razy. Usunąłem kody z poprzednich postów żeby było przejrzyściej.
    A to aktualny kod.
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include "HD44780.c"
    #define F_CPU 1000000
    #define IR_PIN      PD3
    volatile char koniec='1';
    volatile int kod=0;
    volatile int ilosc=0;
    
    int main (void)
    {
    LCD_Initalize();
    LCD_Clear();
    LCD_WriteText("czekam");
    TCCR1B |= (1 << WGM12);
    DDRD =0x01;//
    PORTD=0xff;
    OCR1A = 1778;//porównanie po 1778 impulsach 1 impuls =1us
    TCCR1B |= (1 << CS10) ; // Ustawia timer z preskalerem 1
    
    MCUCR |= (1<<ISC10);
    GICR |= (1<<INT1);//włączenie przerwania od INT1
    
    sei();
    	while(1)
    	{		
    		
    	}
    
    }
    
    
    ISR(TIMER1_COMPA_vect)
    {
    
    	if(PIND & IR_PIN)
    	{
    	
    		kod++;//dodaj 1 do wartości kodu
    		
    	}
    	kod<<=1;//przesuń wartość o 1 pole w lewo
    	ilosc++;
    	if(ilosc==13)
    	{
    		TIMSK &=~ (1 << OCIE1A);// wylaczenie przerwań
    		
    		wypisz();
    		_delay_ms(1000);
    		koniec='1';
    		ilosc=0;
    		GICR |= (1<<INT1);//włączenie przerwań od INT1
    
    
    	}
    
    TCNT1 = 0;//wyzeruj wartość licznika w timerze
    
    }
    
    SIGNAL(INT1_vect)
    {
    GICR &=~ (1<<INT1);//wylacz przerwania od INT1
    PORTD ^= (1 << 0); 
    
    	if(koniec=='1')//sprawdzenie czy instrukcja została pobrana w całości
    		{
    			
    			
    			
    			koniec='0';
    			_delay_ms(0.45);//po pojawieniu się impulsu czekaj
    			if(PIND & IR_PIN )//sprawdź czy impuls nadal jest
    			{
    			TCNT1 = 0;
    			TIMSK |= (1 << OCIE1A);	//włącz przerwania od timera
    			
    			}
    			else koniec='1';
    			
    			
    		}
    }
    
    void wypisz()
    {
    		LCD_Clear();
    
    		if(kod & 0x01) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x02) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x03) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x04) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x05) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x06) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x07) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x08) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x09) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x0a) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x0b) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x0c) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x0d) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		if(kod & 0x0e) LCD_WriteText("1");
    		else LCD_WriteText("0");
    		
    
    
    }
    
REKLAMA