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

Jak optymalnie zmierzyć czas trwania impulsu na Atmega16?

www 17 Lis 2006 11:19 5785 5
REKLAMA
  • #1 3233332
    www
    Poziom 14  
    Posty: 219
    Pomógł: 7
    Ocena: 13
    Witam, mam taki problem i pytam czy wybrane przeze mnie rozwiązanie jest optymalne.
    Musze zmierzyć czas trwania impulsu (logiczna jedynka).

    W tym celu podaje ten sygnał na wyprowadzenie INT0.
    Ustawiam przerwanie INT0 na zbocze narastające.
    Jeśli pojawi się zbocze narastające w funkcji obsługi przerwania ustawiam flage ZN.
    W pętli głównej sprawdzam flage ZN, jeśli jest ustawiona to rekonfiguruje INT0 na zbocze opadające
    i włączam timer, który mierzy mi czas impulsu.
    Jeśli dostane zbocze opadające w funkcji obsługi przerwania ustawiam flage ZO.
    W pętli głównej sprawdzam flage ZO, jeśli jest ustawiona to odczytuje wartość z timera, która
    jest czasem trwania mojego impulsu i znów rekonfiguruje INT0 na zbocze narastające.
    I to byłby koniec cyklu pomiarowego.

    Jeśli macie jakieś inne sugestie proszę o rade.

    Pozdrawiam.
  • REKLAMA
  • #2 3233499
    pubus
    Poziom 30  
    Posty: 1289
    Pomógł: 138
    Ocena: 31
    Ja robiłem to od razu w przerwaniu...
    tzn...
    Kiedy narastające zbocze wywołuje przerwanie...
    W obsłudze odrazu przestawiam rejestr INT0 na reakcję na zbocze opadające i odpalam timer + flaga...
    Po kolejnym przerwaniu mam ustawioną flagę więc zatrzymuje timer i przpisuję jego wartość do zmiennej, przestawiam INT0 i zeruje flagę...
  • REKLAMA
  • #3 3255852
    www
    Poziom 14  
    Posty: 219
    Pomógł: 7
    Ocena: 13
    Racja pubus

    Tak też zrobiłem. Zamieszcze kod, może komuś się przyda:

    
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <math.h>
    #include <string.h>
    #include <avr/interrupt.h>
    
    //ATMega16 Q=4MHz
    
    #define tau0 	87;	//stała czasowa timera0, dla 87 wystepuje przepelnienie licznika po ok 20mS
    short			flPomiar=0;
    bool			flMinCzasTrwania=false;
    bool			flKoniecPomiaru=false;
    
    void czekaj (unsigned long pt);
    
    void czekaj (unsigned long pt) //procedura wytracania czasu
    {
     unsigned char tp1;
    
     for(;pt>0;pt--)
     {
      for(tp1=255;tp1!=0;tp1--);
     }
    }
    
    int main (void)
    {
     DDRD=0x00;        	//PORTD - we
     PORTD=0xFF;       	//podciąganie linii
    
     DDRB=0xFF;        	//PORTB - wy
     PORTB=0x00;      	//zapal LED
    
     DDRC=0xFF;        	//PORTB - wy
     PORTC=0xFF;      	//zgaś LED
    
     DDRA=0xFF;        	//PORTA - wy
     PORTA=0xFF;      	//zgaś LED
    
     // Konfiguracja zewnętrznego przerwania od INT0
     GICR=1<<INT0;		//włącz przerwanie
     MCUCR=1<<ISC00;	//przerwanie wyzwalane zboczem narastającym __|--
     MCUCR=1<<ISC01;
    
     sei();            	//włącz przerwania
    
     while (1)
      {
    PORTC^=0xFF;		//zmień stan LED DEBUG!!!
    
       //Jeśli impuls trwa min. 25mS to coś tam wykonuje
       if (flMinCzasTrwania==true)
       	{
       	 PORTA=0x00;
    	 flMinCzasTrwania=false;
    	}
    	else
       		PORTA=0xFF;
    
       czekaj (32);//32
       asm ("nop");
      }
    }
    
    //Procedura obsługi przerwanie od licznika TC0
    SIGNAL (SIG_OVERFLOW0)
    {
     TCNT0=tau0;			//odśwież stałą czasowa w TCNT0
    
     TIMSK=0<<TOIE0;		//nie zezwalam na przerwanie od TC0
     TCCR0=0;				//wyłączam TC0 kiedy wystąpi przepełnienie
    
     flMinCzasTrwania=true;	//Ustawiam flage która mówi ze impuls trwał min. 25mS
    }
    
    //Procedura obsługi przerwania zewnętrznego od INT0
    SIGNAL(SIG_INTERRUPT0)
    {
     if (flPomiar==0)
     {
      //1. ustawiam przerwanie wyzwalane zboczem opadającym --|__
      MCUCR=0<<ISC00;
      MCUCR=1<<ISC01;
    
      //2. uruchamiam timer
      TIMSK=1<<TOIE0;	//zezwolenie na przerwanie od TC0
      TCNT0=tau0;		//wpisuje stałą czasowa do TCNT0
      TCCR0=5;			//włączam TC0 i ustawiam preskaler na XTAL/1024
    
      //3. ustawiam flage pomiar trwa
      flPomiar=1;
     } else if (flPomiar==1)
     {
      TIMSK=0<<TOIE0;	//nie zezwalam na przerwanie od TC0
      TCCR0=0;			//wyłączam TC0
    
      MCUCR=1<<ISC00;	//przerwanie wyzwalane zboczem narastającym __|--
      MCUCR=1<<ISC01;
    
      flPomiar=0;
      flKoniecPomiaru=true;
     }
    }
    


    Pozdrawiam.
  • REKLAMA
  • #4 3256130
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    www napisał:
    ... Zamieszcze kod, może komuś się przyda:
    
     TIMSK=0<<TOIE0;		//nie zezwalam na przerwanie od TC0
    


    Jeśli już zostawiasz coś po sobie dla potomnych , to zastanów się czy aby nie ma w tym kodzie jakiś "byczków" w stylu j/w :D
    Początkującemu , taka instrukcją może napytać biedy , jeśli będzie np. korzystał z innych przerwań , dostępnych w TIMSK.

    Piotrek
  • REKLAMA
  • #5 3256316
    www
    Poziom 14  
    Posty: 219
    Pomógł: 7
    Ocena: 13
    W sumie to jestem początkujący jeśli chodzi o mikrokontrolery i nie rozumiem Twojej uwagi. Z pdf-a wyczytałem:

    Gdy bit TOIE0 jest zapisany jedynką, zostaje włączone przerwanie przepełnienia Zegar/Licznk0. Odpowiednie przerwanie jest wykonywane jeśli nastąpi przepełnienie w Zegar/Licznik0.

    Więc zapisem:
    TIMSK=0<<TOIE0;
    chciałem to przerwanie anulować.

    Pozdrawiam.
  • #6 3256414
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    www napisał:
    W sumie to jestem początkujący jeśli chodzi o mikrokontrolery i nie rozumiem Twojej uwagi. Z pdf-a wyczytałem:

    Gdy bit TOIE0 jest zapisany jedynką, zostaje włączone przerwanie przepełnienia Zegar/Licznk0. Odpowiednie przerwanie jest wykonywane jeśli nastąpi przepełnienie w Zegar/Licznik0.

    Więc zapisem:
    TIMSK=0<<TOIE0;
    chciałem to przerwanie anulować.

    Pozdrawiam.

    Wyrażenie
     TIMSK=0<<TOIE0

    jest równoważne , a Ty chciałeś zapewne zapisać 0 wyłącznie do bitu TOIE0.Robi się to z użyciem operacji logicznej AND i wygląda to tak
     TIMSK&=~(1<<TOIE0)


    Piotrek
REKLAMA