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

Atmega16, przerwania na Timer0 nie dzialaja tak jak powinny.

Pagodin 18 Maj 2007 14:38 1419 4
REKLAMA
  • #1 3897245
    Pagodin
    Poziom 10  
    Posty: 48
    Witam,

    Napisałem program do odpytywania stanu klawiszy na Atmega16, kwarc-16MHz. Według wyliczeń przerwanie powinno sie pojawiać co 2,5ms, jednak tak nie jest, jest o wiele wolniej (ponad 1s). Analizowałem program i sam juz nie wiem co może być źle. Pomóżcie

    Preskaler clk/1024=16000000/1024=15625
    1/15624=0,064ms
    40*0,064ms=2,5ms



    
    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/interrupt.h>
    
    
    //switche
    #define tau0 256-40;//stala czasowa timera0 
    volatile unsigned char key=0x00;              //informuje o wcisnieci klawisza
    volatile unsigned char key_pressed=0x00;      //przechowuje wartosc klawisza
    enum {WAITING, PUSHING, KEEPING, RELEASEING};  //definicja wartosci wyliczeniowych
    
    volatile unsigned char stan;  
    
    /********/
    
    //...
    //obsluga lcd
    //...
    
    
    /********/
    
    /****************************************************************************/
    // BADANIE SWITCHY
    /****************************************************************************/
    
    SIGNAL (SIG_OVERFLOW0) //obsluga przerwania 
    { 
    
      static unsigned char state = WAITING;     //zmienna dla stanow klawiszy
      unsigned char klawisz=0x00;               //tymczasowa wartosc klawisza w danym cyklu przerwania
      static unsigned char prev_key=0x00;       //przechowuje wartosc poprzedniego klawisza
    
    TCNT0=tau0;
    
    
    	if(!(PIND &1<<PD4)) 
    		{ 
    		klawisz='e'; 
    		} 
    			if(!(PIND &1<<PD6)) 
    			{ 
    			klawisz='p'; 
    			}
    				if(!(PIND &1<<PD3)) 
    				{ 
    				klawisz='c'; 
    				}
    		 			if(!(PIND &1<<PD2))
    					{ 
    					klawisz='l'; 
    					}
    
    
    
     switch(state)                            //przelacz stan klawiszy w zaleznoci od wartosci (eliminacja drgan klawiszy)
        {
            case WAITING:
            {
                if(klawisz)    // jesli krorykolwiek klawisz wcisniety
                {
                    prev_key = klawisz;    //zapisz do wartosci poprzedniej (potrzebna dla zprawdzenia klawisza w kolejnym cyklu przerwania)
                    state = PUSHING;       //zmien stan
                }
                key_pressed = 0x00;
                break;
            }
            case PUSHING:         
            {
                if(prev_key==klawisz)         //jesli klawisz = klawiszowi poprzednio zapisanemu
                {
                    key = prev_key;           //zapisz wartosc klawisza do zmiennej globalnej 'key'
                    state = KEEPING;          //zmieni stan
                }
                else
    			{
    			state = WAITING;   //jesli nierowny to wroc do stanu poprzedniego
    			prev_key=0x00;          //wyczysc wartosc poprzednia klawisza
                key_pressed=0x00;
                }
            	break;
            }
            case KEEPING:                               
            {
                if(prev_key==klawisz)  {}//key= prev_key;    //klawisz caly czas wcisniety, trzymaj wartosc klawisza
                else state = RELEASEING;                 //jesli sie znienil to zmien stan 
                key_pressed=klawisz;
                break;
            }
            case RELEASEING:
            {
                if(prev_key!=klawisz)               //jesli zmiana klawisza
                {
    		 	    key_pressed = 0;//klawisz;             //sygnalizuj gotowosc klawisza do obslugi
                    state = WAITING;                // wroc do poczatku obslugi klawiszy
                    prev_key=0x00;                  //wyczysc wartosc poprzednia klawisza
                }
                else state = KEEPING;             //jesli nie ma zmiany wartosci klawisza to wroc do stanu poprzedniego
                break;
            }
            default:
            {
    			state=WAITING;
                break;
            }
    
    
    
    	}
     
    } 
    
    
    
    /****************************************************************************/
    // MAIN
    /****************************************************************************/
    
    int main(void)
    {
    unsigned char temp[10];
    int liczba=0;
    
    
    //TIMER0
    TIMSK=1<<TOIE0;   //zezwolenie na przerwanie od T0
    TCCR0=5;          //presklaer xtal/1024
    TCNT0=tau0; //wpisz stala
    
    
    DDRA=0xFF;
    
    
    //switch
    DDRD&=~_BV(PD6);
    DDRD&=~_BV(PD4);
    DDRD&=~_BV(PD3);
    DDRD&=~_BV(PD2);
    
    
    lcd_init();
    
    sei();  
    
    
    while(1)
    {
    write_command(0xA8);
    itoa(liczba,temp,10);
    write_text(temp);
    
    
    	switch(key)
    	{
    	case'p':
    			liczba++;
    			key=0x00;
    			break;
    
    	case'l':
    			liczba--;
    			key=0x00;
    			break;
    
    	}
    
    
    }//end while(1)
    
    
    
    
    return 0;
    }
    
    



    Pozdrawiam

    Fuse bity:

    Atmega16, przerwania na Timer0 nie dzialaja tak jak powinny.
  • REKLAMA
  • #2 3919269
    kedzi1
    Poziom 18  
    Posty: 297
    Pomógł: 18
    Ocena: 9
    Spróbuj wywalić wszystko z przerwania i wpisać tam prosty programik, który będzie migał LEDem na jakimś pinie. Okaże się czy obsługa przerwania nie zabiera zbyt dużo czasu procesorowi i czy masz dobry hardware.
  • REKLAMA
  • #3 3919431
    john_t
    Poziom 29  
    Posty: 1070
    Pomógł: 127
    Ocena: 89
    Obsługa przerwania powinna być jak najkrótsza. Twoja obsługa przerwania zajmuje więcej czasu niż okres przerwań. Wszystkie komendy związane z LCD są bardzo złożone i trwają dość długo. Nie powinno się ich umieszczać w obsłudze przerwania.
  • REKLAMA
  • #5 3919590
    kedzi1
    Poziom 18  
    Posty: 297
    Pomógł: 18
    Ocena: 9
    O to mi właśnie chodziło w poprzednim poście. Jak wyrzucisz wszystko z przerwania i wpiszesz tam prosty program kontrolny to upewnisz się że nie masz problemów ze sprzętem a przerwanie jest dobrze policzone. Na oko już widać że podprogram obsługi przerwania będzie wykonywał się dłużej niż 0.25s. W tym czasie mikrokontroler zignoruje kolejne przerwania zanim skończy obsługę bieżącego.
REKLAMA