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

Przenośność kodu ATmega16 do ATmega8L

mgiro 01 Mar 2010 16:26 1620 17
REKLAMA
  • #1 7768798
    mgiro
    Poziom 22  
    Witam,

    Napisałam kod do odbioru protokołu RC5 na ATmega16. Wszystko działa dobrze. Chciałem go zaimplementować na ATmega8L, ale niestety nie działa. Sprawdzałem datasheet, ale nie znalazłem nic, co mogło być przyczyną. Chodzi o Timer1.

    Myślałem, że kod jest bardziej przenośny.

    Proszę o sprawdzenie kodu:

    
    //ATmega8L   kwarc zewnetrzny 4MHz
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile uint16_t g_licznik = 0;
    
    SIGNAL(TIMER1_COMPA_vect)
    {
    	g_licznik++;
    
    }
    int rc5(void)
    {
        {
             TODO
         }
         	TIMSK = 0b00000000; // WYLACZENIE TIMER1
        	g_licznik = 0;
    }
    
    int main(void)
    {
    	int komenda = 0;
    	
    	DDRD =0x00; //wejscia	
            TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
            OCR1A = 25; // Ustawia wartość pożądaną na 20kHz(50us) dla preskalera 8
    	TCCR1B |= (1 << CS11); // Ustawia timer z preskalerem Fcpu/8
    
    
    	sei(); 
           while(1)
          {
            	if(!(PIND & 0x40)) // odbiornik podlaczony do 0b1000000
    		{
    		     TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
    		      komenda = rc5();
    		}
    
    
                    TODO
           }
    
    }
    
    
  • REKLAMA
  • #2 7769614
    rpal
    Poziom 27  
    kolego a co to jest . Kod mozna spokojnie przenosić zwłaszcza kiedy użyje się dla określenia np. pinów i portów. Tym sposobem możesz pisać sobie kod na inny procek a na innym uruchamiać. Zmiana wóczas dotyczy tylko nazw portów i pinów których może inny procek po prostu nie mieć. Szukaj w TODO myślę że to jest przyczyna :)
  • #3 7769696
    mgiro
    Poziom 22  
    Todo to pozostała część programu. Nie wrzucałem jej, bo jak działała na ATmedze16 to i powinna działać na ATmedze8L. Czy się mylę??

    Fuse Bity mam tak ustawione:
    Przenośność kodu ATmega16 do ATmega8L
  • #4 7770790
    rpal
    Poziom 27  
    czy cokolwiek innego działa na tej twoje 8-ce ? może to wina układu ?
  • #5 7770995
    mgiro
    Poziom 22  
    tak, PWM działa. Przyciskami steruje, więc procesor chyba jest dobry.
  • REKLAMA
  • #6 7771215
    czmi3l
    Poziom 14  
    Kolego, byś się zdecydował...
    albo:
    SIGNAL (SIG_OUTPUT_COMPARE1A )

    albo:
    ISR (TIMER1_COMPA_vect) 

    a nie:
    SIGNAL(TIMER1_COMPA_vect) 


    Z tym, że SIGNAL już się nie powinno stosować. A tak to każdy xxxx ma swój strój...

    Konfiguracja Timera jest ok.

    Ja bym delikatnie jeszcze zmienił kod.
    np:
    
               TIMSK = 0b00000000; // WYLACZENIE TIMER1 
    

    Nieprawda, to tylko wyłączenie przerwań, Timer ciągle tyka.

    
               TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
                komenda = rc5();
          }
    

    Zwróć uwagę, że w tym wypadku możesz mieć przerwanie od razu po zezwoleniu na nie. Ja wolę w celu zatrzymania Timera ustawić prescaler na 0 i wyzerować TCNT1 = 0. Uruchomienie Timera to kwestia ustawienie prescalera na poprzednią wartość.
  • #7 7771545
    mgiro
    Poziom 22  
    mi właśnie chodzi o to, żeby mieć przerwanie zaraz po zezwoleniu na nie.
  • #8 7771603
    rpal
    Poziom 27  
    mgiro napisał:
    mi właśnie chodzi o to, żeby mieć przerwanie zaraz po zezwoleniu na nie.

    przerwanie to kolega będzie miał dopiero wtedy jak wyda instrukcję SEI a czy znacznik będzie taki a nie inny albo też wartość licznika siaka lub owaka to bez globalnego zezwolenia na przerwanie i tak się ono nie odbędzie.
  • #9 7771738
    czmi3l
    Poziom 14  
    Ale w kodzie są odblokowane globalne przerwania ;-).
  • REKLAMA
  • #10 7772418
    mgiro
    Poziom 22  
    rpal ale właśnie mam w kodzie odblokowane przerwania sei();

    Zmieniłem zadania Timerow. Teraz Timer1 służy do PWM, a TImer2 do zliczania czasu w dekodowaniu RC5.

    Proszę jeszcze raz o sprawdzenie kodu

    
    //ATmega8L   kwarc 4MHZ
    #include <avr/io.h>
    #include <avr/interrupt.h> 
    #include <util/delay.h>
    
    volatile uint16_t g_licznik = 0;
    
    ISR (TIMER2_COMP_vect)
    {
    	g_licznik++;
    
    }
    
    int rc5(void)
    {
    	uint16_t wiadomosc = 0; 
    
    	{
                  TODO
            }
    
    	
    	TIMSK = 0b00000000; // WYLACZENIE TIMER2
        	g_licznik = 0;
    
    	return wiadomosc & 0b111111;
    
    }
    
    
    int main(void)
    {
    	int szerokosc = 0;
    	int komenda = 0;
    	DDRD =0x00; //wejscia
            PORTD=0x03;  //Podciagniecie do Vcc 0b00000011  PRZYCISKI
    	DDRB = 0x02; // PWM pin OC1A połaczony z diodą 
    	
    
    
    	TCNT1 = 255;       
        OCR1A = 0;   
    	TCCR1A |= (1<<WGM10) | (1<<COM1A1); //8bitowy      
    	TCCR1B |= (1<<CS11) | (1<<CS10); //preskaler 64 
    
                      
          OCR2 = 25; 
          TCCR2 |= (1<<WGM21) | (1<<CS21);   //tryb CTC, preskaler 8       
    
    	sei();
    
    	while(1)
    	{
    		if(!(PIND & 0x40)) // do 0b1000000 podlaczony odbiornik podczerwieni TSOP 1736
    		{
    			TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    		komenda = rc5();
    		}
    	
    	if(komenda == 0x10)
    	{
    		szerokosc += 15;
    		if(szerokosc > 255)
    		{
    			szerokosc = 255;
    			
    		}
    		OCR1A = szerokosc;
    		komenda = 0;
    	}
    	if(komenda == 0x11)
    	{
    		szerokosc -= 15;
    		if(szerokosc < 0)
    		{
    			szerokosc = 0;
    		}
    		OCR1A = szerokosc;
    		komenda = 0;
    		
    	}
    	if(komenda == 0x36)
    	{
    		OCR1A = 0;
    		szerokosc = 0;
    		komenda = 0;
    	
    	}
    	if(komenda == 0x35)
    	{
    		OCR1A = 255;
    		szerokosc = 255;
    		komenda = 0;
    	}
    
    	
    		if(!(PIND & 0x01))
    		{
    			_delay_ms(75);
    			while(!(PIND & 0x01))
    			{
    			}
    			szerokosc += 15;
    			if(szerokosc > 255)
    			{
    				szerokosc = 255;
    			}
    			OCR1A = szerokosc;
    		}
    		if(!(PIND & 0x02))
    		{
    			_delay_ms(75);
    			while(!(PIND & 0x02))
    			{
    			}
    			szerokosc -= 15;
    			if(szerokosc < 0)
    			{
    				szerokosc = 0;
    			}
    			OCR1A = szerokosc;
    		}
    
    
    	}
    }
    
    
  • #11 7773142
    rpal
    Poziom 27  
    a może byś tak użył symulatora albo jtaga jesli go masz i sam zobaczysz co w kodzie nie tak ? Jeśli symulator da wynik pozytywny program jest OK a winny sprzęt.
  • #12 7773533
    mgiro
    Poziom 22  
    no użyłbym, ale ATmega8L nie ma JTAGa. Więc dlatego proszę o sprawdzenie kodu
  • #13 7773684
    zumek
    Poziom 39  
    mgiro napisał:
    Więc dlatego proszę o sprawdzenie kodu

    Nie wiem jaki wpływ na dekodowanie RC5 ma częstotliwość zwiększania zmiennej g_licznik , ale wartość ładowana do OCR, nie zgadza mi się z komentarzem.
    
          OCR1A = 25; // Ustawia wartość pożądaną na 20kHz(50us) dla preskalera 8
    

    Wzór wygląda tak:
    OCRx=F_CPU/prescaler/częstotliwość - 1
  • #14 7774245
    rpal
    Poziom 27  
    mgiro napisał:
    no użyłbym, ale ATmega8L nie ma JTAGa. Więc dlatego proszę o sprawdzenie kodu
    ale masz symulator, przerwanie wyzwolisz przez ustawienie z ręki wskaźnika i obejżysz wszystko na ekranie.
  • REKLAMA
  • Pomocny post
    #16 7775709
    zumek
    Poziom 39  
    mgiro napisał:
    zumek, wartość którą wpisuje do OCR1A obliczyłem wykorzystując ten program...

    A ja Ci podałem wzór, który "stworzyłem" wykorzystując dokumentację ATMega8 :D

    1+OCR2=$$\frac{F_CPU}{N*f}$$
  • #17 7776301
    mgiro
    Poziom 22  
    Zumek, to ten wzór ze strony 109 w dokumentacji??
  • #18 7784262
    mgiro
    Poziom 22  
    dzieki Zumek, Twoj wzór pomógł. Działa ;D
REKLAMA