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

[ATMEGA8][C]Zliczanie, odliczanie 1 sek.

thul 04 Maj 2010 19:44 2818 14
REKLAMA
  • #1 8035119
    thul
    Poziom 10  
    Witam.

    Staram się zrobić program który będzie reagował na wyzwalanie poprzez przycisk (w przyszłości klaskanie). Wejście, do którego podłączony jest przycisk to Port C na wejściu 0x01.

    Cały problem jest następujący:
    - gdy na wejściu podany jest sygnał, zmienna Licznik zwiększa się o jeden.
    - gdy zmienna jest równa 1, to następuje włączenie timera z prescalerem, który odmierza czas 1 sekundy, w trakcie której gdy podamy drugi raz na wejście sygnał zostanie dodana kolejna jedynka.
    - gdy licznik jest rowny 2 zmien stan bitu na wyjściu.

    Program wygląda nastepująco: co robię źle?
    
    #include <avr/io.h>
    #include <util/delay.h>
    int main (void)
    {
    
    DDRB=0x01; //ustawienie pinu 0 portu B na wyjście
    DDRC=0x00; //wejscie klaskacza z portu C
    PORTC=0x01;
    
    TCCR0 |= ((1 << CS00) | (1 << CS01));
    unsigned char licznik = 0;
    
    while(1)
    {
    	if((PINC & 0x01)&(licznik==0))
    	{
    		licznik++;		
    	}
    	_delay_ms(80);
    	if (licznik == 1)
    	{
    		TCNT0=0x00;
    		if(TCNT0 <= 15625)
    		{
    			if ((PINC & 0x01)&(licznik==1))
    			{
    			licznik++;
    			}
    		}
    	}
    	if (licznik == 2)
    	{
    		PORTB ^=0x01;
    	}
    
    }
    }
    


    P.S.
    Dopiero zaczynam przygodę z mikrokontrolerami. Staram się jakoś ugryźć te timery. Myślałem nad zrobieniem tego na przerwaniach, ale zbytnio nie wiem narazie jak sie do tego zabrać.

    Za wszelkie sugestie dziękuję

    Pozdrawiam.
  • REKLAMA
  • #2 8035136
    tadzik85
    Poziom 38  
    Link Polecam ten artykuł. A ten program? Nie wiem co w ten sposób chcesz osiągnąć.
  • REKLAMA
  • #4 8035169
    thul
    Poziom 10  
    chcę osiągnąć to co napisałem - czyli ustawianie wyjścia:

    - gdy wyzwolę wejście, zmienna licznik jest inkrementowana. Wyzwolenie jest bardzo krótkie.

    - gdy ta zmienna jest równa 1 to uruchamiam licznik 1 sekundowy. W czasie tej jednej sekundy gdy podam sygnał na wejście to licznik jest znowu inkrementowany.

    - gdy mam na liczniku 2 to wyjście jest ustawiane odpowiednio.

    Ma to na celu (jezeli chodzi o klaskacz) zminimalizowanie niepożądanego włączania/wyłączania urządzeń ( gdy program jest dostosowany na jeden sygnał wyzwalający)
  • #5 8035248
    tadzik85
    Poziom 38  
    Przekombinowane!.

    Po naciśnięciu klawisza startujesz timer i ustawiasz flagę. Flagę zeruje przerwanie licznika. Jeśli przyciśnięto klawisz i flaga jest ustawiona wykonaj akcje.
  • #6 8035362
    thul
    Poziom 10  
    łatwo mówic ;)

    mógłbyś tak po krótce przedstawić o co chodzi z tymi przerwaniami? od czego zacząć by je jakoś poznać. Nie znam ich jeszcze i starałem się to zrobić na timerze i inkrementowaniu ;)
  • REKLAMA
  • #7 8035443
    tadzik85
    Poziom 38  
    Oto szkielet tego co chcesz zrobić
    volatile char flaga;
    
    ISR(TIMER_OFV_VECT)
    {
    flaga = 0
    //zatrzymaj timer
    return;
    }
    
    if (klawisz)
    {
         if(flaga)
         {
              //timer stop
              akcja;
              flaga = 0;
         }
         else
         {
               //start timer
               flaga =1;
         }
    }
  • REKLAMA
  • #9 8035857
    tadzik85
    Poziom 38  
    Sprawdź w dokumentacji LIBc nazwę tego przerwania.
  • #10 8035975
    thul
    Poziom 10  
    przerobiłem program ale tym razem w ogóle nie reaguje. oto on:
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>        // funkcje sei(), cli() 
    volatile char flaga=0; 
    ISR(TIMER2_OVF_vect)
    {
    flaga = 0 ;
    TCNT2=0X00;//zatrzymaj timer 
    return; 
    } 
    
    int main (void)
    {
    
    DDRB=0x01; //ustawienie pinu 0 portu B na wyjście
    DDRC=0x00; //wejscie klaskacza z portu B
    PORTC=0x01;
    TCCR2 |= ((1 << WGM21));
    OCR2 = 15625; 
    TCCR2 |= ((1 << CS20) | (1 << CS21));
    TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    // TODO: Zezwolenie globalne na przerwania
    
    while(1)
    {
    if (PINC & 0x01) 
    { 
         if(flaga==1) 
         { 
              TCNT2=0x00;
              PORTB ^=0x01; 
              flaga = 0; 
         } 
         else 
         { 
    	 
    	 if (PINC & 0x01) 
    	 {
    	 
               if (TCNT2 <= 15625)
               flaga =1; 
         }} 
    }
    }
    }
  • #11 8036033
    tadzik85
    Poziom 38  
    DDRB=0x01; //ustawienie pinu 0 portu B na wyjście
    DDRC=0x00; //wejscie klaskacza z portu B
    PORTC=0x01;
    nad tym się zdecyduj

    Stosując przerwanie nie testuje się zawartości licznika
     if (TCNT2 <= 15625)
    ZLE

    TCCR2 |= ((1 << WGM21));
    OCR2 = 15625; 
    TCCR2 |= ((1 << CS20) | (1 << CS21));
    TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    oraz
    ISR(TIMER2_OVF_vect)
    Zdecyduj się jaki tryb licznika wykorzystujesz

    OCR2 = 15625; 
    timer 2 jest 8-bitowy !
  • #12 8036375
    thul
    Poziom 10  
    poprawiłem na timer1.

    Tylko, że to działa mi teraz za każdym razem gdy wyzwolone zostaje wejście.

    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>        // funkcje sei(), cli() 
    volatile char flaga; 
    ISR(TIMER1_OFV_vect)
    {
    flaga = 0 ;
    TCNT1=0X00;//zatrzymaj timer 
    return; 
    } 
    
    int main (void)
    {
    
    DDRB=0x01; //ustawienie pinu 0 portu B na wyjście
    DDRC=0x00; //wejscie klaskacza z portu C
    PORTC=0x01;
    TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
    OCR1A = 15625; // Ustawia wartość pożądaną na 1Hz dla preskalera 64
    TCCR1B |= ((1 << CS10) | (1 << CS11)); // Ustawia timer z preskalerem Fcpu/64
    TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
    sei(); // Zezwolenie globalne na przerwania
    
    while(1)
    {
    if (PINC & 0x01) 
    { 
    flaga==0;
         if(flaga==1) 
         { 
              TCNT1=0x00;
              PORTB ^=0x01; 
              flaga = 0; 
         } 
         else 
         { 
    	 
    	 if (PINC & 0x01) 
    	 {
    	 
               TCNT1=0x01;
               flaga =1; 
         }} 
    }
    }
    }
  • #13 8036437
    tadzik85
    Poziom 38  
    cóż to za cudo?

    Wykorzystujesz przerwanie
    TIMER1_OFV_vect
    a licznik ustawiasz w tryb CTC z wykorzystaniem COMPA. nic dziwnego ze nie działa.

    2 sprawdzenie czy wciśnięto klawisz zbyteczne.

    if(flaga==1)
         {
              TCNT1=0x00;  


    nie tylko zeruj licznik ale i włącz go, bo
    tylko zeruje licznik a nie zatrzymuje

    Dodano po 4 [minuty]:
    Ma byc tak: (pisane na sucho)
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>        // funkcje sei(), cli()
    volatile char flaga =0;
    ISR(TIMER1_COMPA_vect)
    {
    flaga = 0 ;
    TCCR1B &= ~((1 << CS10) | (1 << CS11));
    TCNT1=0x00;//zatrzymaj timer
    return;
    }
    
    int main (void)
    {
    
    DDRB=0x01; //ustawienie pinu 0 portu B na wyjście
    DDRC=0x00; //wejscie klaskacza z portu C
    PORTC=0x01;
    TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
    OCR1A = 15625; // Ustawia wartość pożądaną na 1Hz dla preskalera 64
    //TCCR1B |= ((1 << CS10) | (1 << CS11)); // Ustawia timer z preskalerem Fcpu/64
    TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
    sei(); // Zezwolenie globalne na przerwania
    
    while(1)
    {
    if (PINC & 0x01)
    {
         if(flaga==1)
         {
              TCNT1=0x00;
              TCCR1B &= ~((1 << CS10) | (1 << CS11));
              PORTB ^=0x01;
              flaga = 0;
    // tu co co chcesz zrobić
         }
         else
         {   
               TCNT1=0x00;
               TCCR1B |= ((1 << CS10) | (1 << CS11))
               flaga = 1;
         }
    }
    }
    }
  • #14 8036519
    thul
    Poziom 10  
    Tryb ctc usunąć i timer ustawić w tryb normalny by przerwania zadziałały?
  • #15 8036536
    tadzik85
    Poziom 38  
    Zrobiłem ci gotowca dla trybu CTC. Przeczytaj od deski do deski artykuł, który ci podałem na wstępie.
REKLAMA