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

[attiny2313][avr-gcc]problem z timerem 1

ktosikej 17 Wrz 2009 10:38 1889 4
REKLAMA
  • #1 7027176
    ktosikej
    Poziom 2  
    Właśnie zaczynam zabawę z programowaniem mojego układu i chciałem nauczyć się wykonywania pomiarów czasu ale prawdopodobnie mam źle skonfigurowanego timera. Przejrzałem sporo tematów tutaj i nie tylko, czytałem datasheeta i dalej tego nie rozumiem.

    Program jak na razie ma mierzyć czas po jakim pojawi się impuls na porcie D i wyświetlać rząd wielkości czasu na wyświetlaczu 8 segmentowym podpiętym do portu B. W przyszłości będę potrzebował dużej dokładności pomiaru czasu dlatego zdecydowałem się na używanie timera 1.

    Do attiny2313 jest podpięty zewnętrzny kwarc 10MHz.

    Symulator pokazuje, że program nie wchodzi mi w ogóle do obsługi przerwania zegara.

    kod programu:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    int czas = 0;
    
    unsigned char digitToSend(unsigned char Digit)
    {
    	switch (Digit)
    	{
    		case 0: return 0b00000001; 
    		case 1: return 0b01111001; 
    		case 2: return 0b00010010; 
    		case 3: return 0b00000110; 
    		case 4: return 0b01001100; 
    		case 5: return 0b00100100; 
    		case 6: return 0b01100000; 
    		case 7: return 0b00001111; 
    		case 8: return 0b00000000; 
    		case 9: return 0b00001100; 
    		default: return 0b00110000;
    	}
    }
    
    SIGNAL (SIG_OVERFLOW1)	
    {
    	TCNT1 = 0x00;
    	czas++;
    }
    
    int main(void)
    {
    	unsigned int pomiarczasu;
    	unsigned char rzadwielkosci = 0;
    
    	DDRD = 0x00;	
    	DDRB = 0xFF;	
    	PORTB = 0xFF;	
    
    	TCNT1=0x00;		
    	TCCR1A=0x00;	
    	TCCR1B = 0x01;
    
    	//czekamy na wyzerowanie nozki
    	while(!(PIND & 1));
    
    	//sprawdzamy po jakim czasie na ostatniej nozce portu d pojawi sie 1; 
    	sei();
    	czas=0;
    	while (PIND & 1);		
    	cli();
    	pomiarczasu = czas;
    	
    	while(pomiarczasu >= 10)
    	{
    		pomiarczasu = pomiarczasu / 10;
    		rzadwielkosci++;
    	}
    	
    	PORTB = digitToSend(rzadwielkosci);
    
    	return 0;
    }
    
  • REKLAMA
  • REKLAMA
  • #3 7027222
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Nie mówiąc już o (jak zwykle) braku volatile.

    Program jest źle napisany - po jednym pomiarze (załóżmy, że taki się dokona, co oczywiście nie jest prawdą) procek się resetuje, nigdy nie zobaczysz wyniku na wyświetlaczu.

    4\/3!!
  • REKLAMA
  • #4 7027287
    ktosikej
    Poziom 2  
    Założyłem, że cli() zatrzymuje przerywania już po dokonanym pomiarze czasu tym samym zatrzymuje sam pomiar. Po wywaleniu cli także nie wchodzi do obsługi przerywania.

    Wyszedłem z założenia że program ma prawo działać poprawnie na układzie dopiero jeżeli będzie działał poprawnie na symulatorze, więc jak na razie testuję tylko na nim, gdzie wygodniej mi było robić to bez pętli opóźniającej czy nieskończonej pozwalającej zobaczyć wyniki na układzie.

    Dodałem volatile do wszystkich zmiennych.
  • #5 7027301
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Nie do WSZYSTKICH, tylko do tych które są używane w przerwaniach i "głównym wątku" jednocześnie (czas)

    jeśli chcesz, żeby Timer wywoływał przerwanie, to warto zainteresować się rejestrem TIMSK (albo jakaś podobna nazwa), w którym można je włączyć, bo na razie nie ma takiej opcji, żeby program wszedł do tego przerwania.

    4\/3!!
REKLAMA