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

ATmega32, jak poprawnie ustawić przerwanie TIMER1 w C na zestawie and-tech EvB 4.3

atek000 29 Gru 2011 17:23 1620 4
REKLAMA
  • #1 10319592
    atek000
    Poziom 18  
    Posty: 293
    Pomógł: 6
    Ocena: 46
    Witam wszystkich. W końcu wziąłem się za naukę C, tym bardziej, że zakupiłem książkę naszego forumowicza mirka (polecam książkę, lekko napisana i ta po "chłopsku") oraz wpadł mi w ręce zestaw startowy z and-tech EvB 4.3
    (bardzo podobny do tego z ATNEL-a). Pierwsze kroki z diodą i wyświetlaczem LCD za mną. Przerwanie i migoczącą diodą także.

    Problem mam z konfiguracją przerwania TIMER1
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    //----definicja segmentow----
    #define sA (1<<PC0)
    #define sB (1<<PC1)
    #define sC (1<<PC2)
    #define sD (1<<PC3)
    #define sE (1<<PC4)
    #define sF (1<<PC5)
    #define sG (1<<PC6)
    
    //----definicja cyfr------
    #define c0 ( sG)
    #define c1 ( sA | sD | sE | sF | sG)
    #define c2 ( sC | sF)
    #define c3 ( sE | sF)
    #define c4 ( sA | sD | sE)
    #define c5 ( sB | sE)
    #define c6 ( sB)
    #define c7 ( sD | sE | sF | sG)
    #define c8 (0)
    #define c9 ( sE)
    #define ce ( sB |sC)
    
    //----zmienne globalne----
    uint8_t zn,CAX;
    
    uint8_t *wsk;
    
    // --- *** Program Glowny *** ---
    int main(void)
    {
    	DDRC |= (sA | sB | sC | sD | sE | sF | sG); //piny do lcd
    	DDRA |= (1<<PA0);							//pin do diody
    
    //--- konfiguracja przerwania ---
    	TCCR1B |= (1<<WGM12);					//ustawienie TIMER1 w tryb CTC
    	TCCR1B |= ((1<<CS12)|(1<<CS10));		//ustawienie prescalera
    	OCR1A =15625;							//wartosc w rejestrze do porownania
    	TIMSK |= ((1<<OCIE1A) | (1<<OCIE1B));	//zezwolenie na przerwanie od timer1
    	sei();
    
    	CAX=1;									//ot takie sobie przypisanie
    //--- petla---
    	while(1)
    	{
    		zn=CAX;
    
    		switch (zn)				//konwersja cyfry na konkretne segmenty
    		{
    			case 0:
    				zn=c0;
    				break;
    			case 1:
    				zn=c1;
    				break;
    			case 2:
    				zn=c2;
    				break;
    			case 3:
    				zn=c3;
    				break;
    			case 4:
    				zn=c4;
    				break;
    			case 5:
    				zn=c5;
    				break;
    			case 6:
    				zn=c6;
    				break;
    			case 7:
    				zn=c7;
    				break;
    			case 8:
    				zn=c8;
    				break;
    			case 9:
    				zn=c9;
    				break;
    			default:
    				zn=ce;
    		}
    		PORTC=zn;					//wyslanie cyfry juz zamienionej
    portu C
    
    		wsk=&CAX;
    		++*wsk;
    		if (*wsk>=10) *wsk=0;
    		PORTA ^=(1<<PA0);			//zmiana stanu diody
    		_delay_ms(4000);
    
    	}
    }
    
    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {
    
    }
    


    Wiem że kod jest nieco zagmatwany i niepotrzebne są wskaźniki i przerwanie ale właśnie się ich uczyłem i dlatego zastosowałem.
    W tym przypadku włączone jest przerwanie, ale jest puste. Wykonywać powinien się tylko główny program zliczający CAX, "przekonwertować" na odpowiednie segmenty, wysłać do portu c, zwiększyć CAX, zmienić stan dodatkowej diody na PA0, odczekać 4s i ... tyle, wraca i robi znów to samo. Międzyczasie wykonuje się puste przerwanie co 1s.
    Natomiast u mnie dioda miga co 1s a na LCD mam wciąż cyfrę 1, jaka był przypisana na początku jeszcze przed pętlą.

    Program działa prawidłowo jeżeli całą konfigurację przerwania oraz samo przerwanie ujmę w komentarz.
    
    /*
    //--- konfiguracja przerwania ---
    	TCCR1B |= (1<<WGM12);					//ustawienie TIMER1 w tryb CTC
    	TCCR1B |= ((1<<CS12)|(1<<CS10));		//ustawienie prescalera
    	OCR1A =15625;							//wartosc w rejestrze do porownania
    	TIMSK |= ((1<<OCIE1A) | (1<<OCIE1B));	//zezwolenie na przerwanie od timer1
    	sei();
    */
    


    
    /*
    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {
    
    }
    */
    


    Wówczas wyświetlana cyfra się zwiększa wraz ze zmianą stanu diody co 4s.
  • REKLAMA
  • Pomocny post
    #2 10319633
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    a co z przerwaniem porównania kanału B?
  • REKLAMA
  • #3 10319889
    atek000
    Poziom 18  
    Posty: 293
    Pomógł: 6
    Ocena: 46
    Faktycznie, nie mam pojęcia po co wpisywałem OCIE1B. Pozostawiłem
    	TIMSK |= (1<<OCIE1A);	//zezwolenie na przerwanie od timer1
    i jest teraz ok.
    Tą konfigurację robiłem jakiś czas temu i chyba myślałem że trzeba załączyć A i B.


    Teraz zmiana i dążenia właśnie do tego co zamierzałem i znów zong. Zliczanie miało odbywać się w przerwaniu. Wiem, że przerwanie to swego rodzaju funkcja a do funkcji z niej należy zmienne przekazywać. Ja właśnie chciałem użyć wskaźników.
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    //----definicja segmentow----
    #define sA (1<<PC0)
    #define sB (1<<PC1)
    #define sC (1<<PC2)
    #define sD (1<<PC3)
    #define sE (1<<PC4)
    #define sF (1<<PC5)
    #define sG (1<<PC6)
    
    //----definicja cyfr------
    #define c0 ( sG)
    #define c1 ( sA | sD | sE | sF | sG)
    #define c2 ( sC | sF)
    #define c3 ( sE | sF)
    #define c4 ( sA | sD | sE)
    #define c5 ( sB | sE)
    #define c6 ( sB)
    #define c7 ( sD | sE | sF | sG)
    #define c8 (0)
    #define c9 ( sE)
    #define ce ( sB |sC)
    
    //----zmienne globalne----
    uint8_t zn,CAX;
    
    uint8_t *wsk;
    
    // --- *** Program Glowny *** ---
    int main(void)
    {
    	DDRC |= (sA | sB | sC | sD | sE | sF | sG); //piny do lcd
    	DDRA |= (1<<PA0);							//pin do diody
    
    //--- konfiguracja przerwania ---
    	TCCR1B |= (1<<WGM12);					//ustawienie TIMER1 w tryb CTC
    	TCCR1B |= ((1<<CS12)|(1<<CS10));		//ustawienie prescalera
    	OCR1A = 15625;							//wartosc w rejestrze do porownania
    	TIMSK |= (1<<OCIE1A);	//zezwolenie na przerwanie od timer1
    	sei();
    
    	CAX=1;									//ot takie sobie przypisanie
    //--- petla ---
    	while(1)
    	{
    		zn=CAX;
    
    		switch (zn)				//konwersja cyfry na konkretne segmenty
    		{
    			case 0:
    				zn=c0;
    				break;
    			case 1:
    				zn=c1;
    				break;
    			case 2:
    				zn=c2;
    				break;
    			case 3:
    				zn=c3;
    				break;
    			case 4:
    				zn=c4;
    				break;
    			case 5:
    				zn=c5;
    				break;
    			case 6:
    				zn=c6;
    				break;
    			case 7:
    				zn=c7;
    				break;
    			case 8:
    				zn=c8;
    				break;
    			case 9:
    				zn=c9;
    				break;
    			default:
    				zn=ce;
    		}
    		PORTC=zn;					//wyslanie cyfry juz zamienionej na port C
    	}
    }
    
    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {
            wsk=&CAX;
    	++*wsk;
            if (*wsk>=10) *wsk=0;
            PORTA ^=(1<<PA0);         //zmiana stanu diody
    }


    No i dioda miga a cyfra się nie zmienia.
  • REKLAMA
  • Pomocny post
    #4 10320416
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    słowo kluczowe "volatile"
  • #5 10320840
    atek000
    Poziom 18  
    Posty: 293
    Pomógł: 6
    Ocena: 46
    Faktycznie, dziękuję i ponownie poleciał przycisk "pomógł". Źle zrozumiałem opis z książki str.79. Dzisiaj poprawiłem wiadomości z przerwania od TIMER1, zapoznałem się ze wskaźnikami i zmiennymi typu "volatile". Dzień był udany :D
REKLAMA