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][C] odmierzanie czasu (przerwania)

svensonie 06 Cze 2010 21:42 2249 6
REKLAMA
  • #1 8162992
    svensonie
    Poziom 11  
    Mam do zrobienia program o następującym działaniu: przerwaniem zewnętrznym (INT0) uruchamiam całą machinę - czas zaczyna być mierzony, kolejnym przerwaniem zewnętrznym (INT1) robię STOP, i w tym momencie wynik powinien być wyświetlony na wyświetlaczu LCD. Niestety jak chce odpalić program już na płytce to się nic kompletnie nie dzieje. Zapewne coś jest nie tak z przerwaniami. Poniżej zamieszczam kod.

    
    #define F_CPU 1000000 
    //#include <avr/timer.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    #include "char_code.h"
    #include "LCD_lib.h"
    
    //#include <stdlib.h>
    
    
    volatile uint8_t licznik = 0; //inkremetuje sie jest przepelnienie licznika
    volatile uint8_t mili_sek = 0;
    volatile uint8_t setna_sek = 0;
    volatile uint8_t dziesiata_sek = 0;
    volatile uint8_t sekunda = 0;
    volatile uint8_t dziesiatki_sek = 0;
    volatile uint8_t flaga = 1;
    volatile uint8_t ms = 0;
    volatile uint8_t ss = 0;
    volatile uint8_t da_s = 0;
    volatile uint8_t s = 0;
    volatile uint8_t di_s = 0;
    
    
    SIGNAL (SIG_INTERRUPT0){
      //timer0_start();
      TCNT0 = 0;    //bedzie liczyl od zera
      TIMSK |= (1 << TOIE0);	//aktywacja przerwan timerow
      flaga = 1; 	//flaga sluzaca do wyswietlania wynikow
      
    } 
    
    
    SIGNAL (SIG_INTERRUPT1){
    	TIMSK |= (0 << TOIE0);	//wylaczenie przerwan od timerow
      //timer0_stop();
      	ms = konwertuj(mili_sek);
    	ss = konwertuj(setna_sek);
      	da_s = konwertuj(dziesiata_sek);
    	s = konwertuj(sekunda);
    	di_s = konwertuj(dziesiatki_sek);
    	flaga = 0;
    
    } 
    
    SIGNAL (SIG_OVERFLOW0) {
    	licznik = licznik+1;
    	if (licznik == 2) {
    	licznik = 0;
    	mili_sek = mili_sek+1;
    		if(mili_sek == 10) {
    		mili_sek = 0;
    		setna_sek = setna_sek+1; 
    			if(setna_sek == 10) {
    			setna_sek = 0;
    			dziesiata_sek = dziesiata_sek+1;
    				if(dziesiata_sek == 10) {
    				dziesiata_sek = 0;
    				sekunda = sekunda+1;
    					if(sekunda == 10) {
    					sekunda = 0;
    					dziesiatki_sek = dziesiatki_sek+1;
    									   }
    									     }
    								 }
    							}
    						  } 	 	 		 		
    	
    	TCNT0 = 0;
    
    }
    
    
    
    int main(void) {
    
    DDRD = 0x00; 
    
    //timer0_source(TCCR0);
    OCR0 = 250;	//249;  F9
    TCCR0 = 10;// 	CS01 = 1;	WGM01 = 1;WGM00 = 0;
    //CS02 = 0;
    //CS01 = 1;
    //CS00 = 0;
    TIMSK = 130;//OCIE0 = 1;
    //TIMSK = _BV(TOIE0);
    
    
    MCUCR = ((1<<ISC01)|(0<<ISC00)); 
    MCUCR = ((1<<ISC11)|(0<<ISC10));
    //GICR |= _BV(INT0)| _BV(INT1); 
    GICR |= ((1<<INT0)|(1<<INT1));
    DDRD = 0x00;
    sei();
    
    while(!flaga) {		//petla odpowiedzialna za wyswietlenie wyniku
    LCD(di_s, 1, 0, 1);
    LCD(s, 1, 0, 2);
    LCD(kropka, 1, 0, 3);
    LCD(da_s, 1, 0, 4);
    LCD(ss, 1, 0, 5);
    LCD(ms, 1, 0, 6);
    
    }
    }
    
  • REKLAMA
  • REKLAMA
  • #3 8179719
    svensonie
    Poziom 11  
    Dobre pytanie, a jaką komendą odpala się licznik?
  • REKLAMA
  • #4 8181607
    Karol966
    Poziom 31  
    Odsyłam do aplikacji ;)
    http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
    Strona 88 i dalej.

    Ja to robię np tak:
    
    #define TIMER0_ON	TCCR0 = 0x02;
    #define TIMER0_OFF	TCCR0 = 0x00;
    #define TIMER1_ON	TCCR1B = 0x02;
    #define TIMER1_OFF	TCCR1B = 0x00;
    
  • #5 8182973
    svensonie
    Poziom 11  
    Cytat:


    Ja to robię np tak:
    Kod:

    #define TIMER0_ON TCCR0 = 0x02;
    #define TIMER0_OFF TCCR0 = 0x00;
    #define TIMER1_ON TCCR1B = 0x02;
    #define TIMER1_OFF TCCR1B = 0x00;



    Z tego co się orientuje to zmieniasz tutaj bit CS02, który jest odpowiedzialny za przeskalowanie częstotliwości zegara. Ja go w sumie ustawilem w mainie:

    Cytat:


    TCCR0 = 10;


    Także twój sposób chyba nie włącza i wyłącza licznika, chyba że źle myślę
  • #6 8183168
    janbernat
    Poziom 38  
    Dlaczego w przerwaniach zewnętrznych zezwalasz/blokujesz obsługę przerwania od Timer0- bo nie od timerów ale tylko od TIMER0.
    Zezwolenie ma obsługę przerwania od przepełnienia TIMER0 powinno być w main.
    Podobnie ustawienie bitów CS00- CS02.
    Ustawienie ich na 0,0,0 powoduje zatrzymanie licznika.
    To może być czasem potrzebne- ale nie w Twoim programie.
    W przerwaniu INT1 zerujesz licznik i ew ustawiasz flagę.
    W przerwaniu INT0 przepisujesz stan licznika do jakiejś zmiennej i w pętli głównej wyświetlasz.
    Licznik się dalej kręci- ale i tak go wyzeruje przerwanie INT1.
    Jeśli czas jest dłuższy niż licznik- to trzeba w każdym przerwaniu od licznika inkrementować jakąś zmienną- a potem pomnożyć przez nią długość licznika i dodać wartość z INT0.
  • REKLAMA
  • #7 8211633
    elonica
    Poziom 12  
    TIMSK |= (0 << TOIE0); //wylaczenie przerwan od timerow

    To raczej tak powinno wyglądać:

    TIMSK &= ~(1 << TOIE0);
REKLAMA