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

[ATmega32][C] Zależność liczników 8 bitowych

slabyG 09 Gru 2008 14:16 951 1
  • #1 5837212
    slabyG
    Poziom 2  
    Witam!

    Mam mały problem z licznikami w Atmedze32.
    Na początek kod:

    
    
    void IR_Generuj()
    {		
            //TUTAJ WŁĄCZAM TIMER KLUCZUJĄCY SYGNAŁ//
    
    	TIMSK|=1<<OCIE2;
    	OCR2=75;
    	TCCR2 = 1<<WGM21 | 1<<CS21; //PRESK 8 |TRYB CTC
    		
    		  
            //TUTAJ GENERUJE SYGNAŁ 36kHz//
    
            OCR0=13;  //(int)(1000000*(1/76000));
           	TCCR0 =  1<<CS00|1<<COM00| 1<<WGM01; //bez presk|toggle na oc0|tryb ctc
         		
    				while(!koniec){};
    		 		koniec = 0;
    	 			 
    	 			
    	 		
    }
    
    // TUTAJ WYŁĄCZAM TIMERY po 600us//
    
    ISR(SIG_OUTPUT_COMPARE2)
    { 
              
        TIMSK=0;
        koniec = 1;
    	PORTB &=~(1<<3);
       	TCCR0 &=~( 1<<CS00|1<<COM00| 1<<WGM01);
        TCCR1B &=~(1<<CS11|1<<WGM12 );
    	 
    }


    Jak widać program ma działać na 2 licznikach (0 i 2). Timer 0 pracuje w trybie toggle generując przebieg prostokątny na OC0 z częstotliwością 36kHz. Sama generacja działa poprawnie (oscyloskop nie kłamie). Jednak jak próbuję włączać i wyłączać generację tego przebiegu powiedzmy na 600 us, i używam do tego timera 2 (8bitowego) to wtedy nie działa tak jak powinno. Sygnał się sypie, kluczowanie jest losowe.

    Pytanie: czy te liczniki działają zależnie? Czy rzuca się w oczy jakiś błąd w kodzie? Może źle rozumuje?

    P.S. jak w AVRGCC zaokrąglać liczby stałoprzecinkowe do całkowitych? polecenie (int)(1000000*(1/76000)) które w wyniki daje liczbę 13 nie działa. Program się kompiluje ale sygnał ma ogromną częstotliwość.

    Wielkie dzięki za pomoc niewprawionemu programiście!
    Pozdrawiam!
  • #2 5837532
    Dr.Vee
    VIP Zasłużony dla elektroda
    Timer0 i Timer1 mają wspólny preskaler, Timer2 ma osobny preskaler. Poczytaj o resetowaniu preskalera w dokumentacji.

    U Ciebie jest inny błąd, w przerwaniu OC2 zmieniasz TCCR1B zamiast TCCR2.

    Co do zaokrąglania, to 1/76000 jest obliczane wg. zasad arytmetyki liczb całkowitych, a więc wynikiem operacji jest 0.
    Najprościej policzyć to tak:
    
    OCR0 = (1000000+76000/2)/76000;

    Drugi człon ma za zadanie prawidłowe zaokrąglenie wyniku.

    Ewentualnie, przy optymalizacji oraz wystarczająco inteligentnym kompilatorze (avr-gcc tutaj pasuje ;) ), możesz napisać po prostu:
    OCR0 = round(1000000*(1.0/76000));


    Pozdrawiam,
    Dr.Vee
REKLAMA