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

[C][przerwania] niedokładny pomiar czasu

chmurli 10 Wrz 2009 21:35 1389 11
  • #1 7003931
    chmurli
    Poziom 10  
    witam, piszę program metronomu i potrzebuję dokładny pomiar czasu.
    zauważyłem jednak że cały czas nie mogę uzyskać dokładnego odmierzania, ustawiam np. 60 taktow na minutę, a otrzymuję ok.63 (mierzyłem kilkakrotnie stoperem).
    próbowałem z różnymi preskalerami i zawsze program się spieszy.
    załączam prosty testowy program jako przykład. diody mają się zapalać na sekundę i gasnąć na sekundę (też program się "spieszy" )
    czy może to być wina kwarcu (8MHz)?


    #include <avr\io.h>
    #include <inttypes.h>
    #include <avr\signal.h>
    #include <avr\interrupt.h>
    
    
    
    // Definicje wyprowadzeń
    #define LED_A 4
    #define LED_B 3
    #define LED_C 5
    #define LED_D 2
    #define LED_E 6
    #define LED_F 0
    #define LED_G 7
    #define LED_DP 1
    #define LEDPORT PORTB
    #define LEDDDR DDRB
    #define COM1 5
    #define COM2 4
    #define COM3 3
    #define COM4 2
    #define COMPORT PORTD
    #define COMDDR DDRD
    #define SWPORT PORTE
    #define SWDDR DDRE
    #define SWPIN PINE
    #define SW1 0
    #define SW2 2
    #define BPMDDR DDRA
    #define BPMPORT PORTA
    #define BUZZ 0
    #define D1 1
    #define D2 2
    
    
    uint8_t t=0;
    
    
    SIGNAL(SIG_OVERFLOW1)
    {
    
    	//TCNT1 = (0xFFFF - 31250);
    	TCNT1L =0xEE; 
    	TCNT1H =0x85;
    	
    	
    	if (t==0) {
    		COMDDR = 0x00;
    		t=1;
    	} else {
    		COMDDR = 1<<COM1;
    		t=0;
    	}
    }
    
    
    
    int main(void)
    {
    
    	LEDDDR = 1<<LED_A | 1<<LED_D; 
    	
    	
    	// Timer1 16-bit
    	//TCNT1 = (0xFFFF - 31250); 	// Wartość początkowa
    	TCNT1L =0xEE; 
    	TCNT1H =0x85;
    	
    	TCCR1B = 1<<CS12; 			// Preskaler 256
    	
    	
    	TIMSK = 1<<TOIE1;
    	sei();
    	
    	COMDDR = 1<<COM1;
    	while(1) {   
      
    	
      
      
    	}
    }
  • #2 7003951
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Jeśli zamiast dokładnego trybu porównania (compare), korzystasz z niedokładnego trybu przepełnienia (overflow), to czemu się dziwisz?

    TCNT1L =0xEE;
    TCNT1H =0x85;

    ślicznie sobie wszystko policzyłeś, ale zapomniałeś, że zanim procesor doszedł do tego wpisywania, to trochę czasu już upłynęło. Dokładnie upłynęło 3/60 czasu który chcesz odmierzać.

    4\/3!!
  • #3 7004262
    chmurli
    Poziom 10  
    Cytat:
    ślicznie sobie wszystko policzyłeś, ale zapomniałeś, że zanim procesor doszedł do tego wpisywania, to trochę czasu już upłynęło. Dokładnie upłynęło 3/60 czasu który chcesz odmierzać.


    czy możesz wyjaśnić jak to policzyłeś? z tego co wiem to cykl rozkazowy powinien trwać kilkadziesiąt krotnie krócej niż impuls zliczający na liczniku (mikroprocesor pracuje z f=8Mhz, a licznik 256 razy wolniej, więc wpływ powinien być pomijalny. jeżeli moje rozumowanie jest błędne to przepraszam i prosze o wyjaśnienie
  • #4 7004498
    Konto nie istnieje
    Poziom 1  
  • #5 7005350
    chmurli
    Poziom 10  
    chyba zapomniałem napisać że do układu dołączony jest zewnętrzny rezonator 8MHz. układ chyba sam się ustawia na jego taktowonie, czy może trzeba coś ustawiać?
  • #6 7005455
    Banan-PL
    Poziom 12  
    chmurli napisał:
    układ chyba sam się ustawia na jego taktowanie, czy może trzeba coś ustawiać?


    Nic się samo nie ustawia, samo podłączenie nic nie da - wtedy pracuje na wewnętrznym oscylatorze. Jak wyżej napisano dlatego pewnie liczy niedokładnie.

    Do pracy na kwarcu konieczne jest ustawienie Fuse Bitów.
  • #7 7005687
    chmurli
    Poziom 10  
    dzięki, ustawiłem fusebity na zew. zegar i teraz liczy dokładnie.
  • #8 7010780
    tmf
    VIP Zasłużony dla elektroda
    Masz jeszcze inne bledy - TCNT1H musi byc zapisany przed TCNT1L - poczytaj sekcje DS - Accessing 16-bit registers. Albo po prostu zapisuj TCNT1 jako 16 bitowy rejestr - kompilator sam sie zatroszczy o wlasciwa kolejnosc zapisow. Zapisywanie tego rejestru ponownie w przerwaniu nie jest konieczne.
  • #9 7010848
    Konto nie istnieje
    Poziom 1  
  • #10 7010978
    kwesoly
    Poziom 15  
    atom1477 napisał:

    W takim razie bardzo się dziwię że to działa.

    W wspomnianej sekcji jest napisane, że do zapisu takich 16 bitowych rejestrów używa się tymczasowego rejestru 8 biotwego, do przechowywania wartości xxxH przy zapisie. Jako, że program nie zapisuje żadnego innego xxxH to wartość tymczasowa nie licząc pierwszego zapisu jest tam poprawna.
  • #12 7011011
    Konto nie istnieje
    Poziom 1  
REKLAMA