- Labornetzteil AliExpress         
Ergebnis 1 bis 2 von 2

Thema: PWM/Timer wie auch immer. Kann so nich sein

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    06.02.2007
    Ort
    Aachen
    Beiträge
    19

    PWM/Timer wie auch immer. Kann so nich sein

    Anzeige

    Powerstation Test
    Hallo zusammen.

    Ich versuche langsam die Timer des AVRs zu verstehen und zu programmieren. Klappt soweit auch wunderbar, nur bin ich jetzt an einer Stelle an der ich nicht alleine weiterkomme. Ich habe ein kleines Programm geschrieben, dass eine LED an- und ausschaltet. Dies soll im Sekundentakt geschehen.

    Ich habe es in sofern realisiert, dass ich in einem definierten Zeitintervall immer wieder einen Interrupt auslöse, dort eine Variable um den Wert eins erhöhe und diese somit zu meinem Zeitmesser mache.

    Jetzt habe ich aber einen Zeitunterschied, den ich mir nicht erklären kann: Wenn ich den Interrupt "seltener" auslöse, ist die Sekunde auch eine Sekunde lang (soweit ich das messen kann). Löse ich den Interrupt jedoch häufiger aus so ist meine definierte Sekunde keine Sekunde mehr lang.

    Hier der Code:
    Code:
    #include <stdlib.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile long x,i;
    
    void timerinit(void)
    {
    DDRC = 0xFF;
    PORTC = 0x00;
    TCCR1A=0;
    TCCR1B = (1<<CS10)|(0<<CS11)|(0<<CS12) ;   // Teiler = 1 -> 16MHZ
    TIMSK |= (1<< TOIE1);
    sei();  
    }
    
    
    int main(void)
    {
    long j;
    timerinit();
    for (;;) {}
    }
    
    //Sehr lange Sekunde, ca. 3 Sekunden:
    ISR (TIMER1_OVF_vect)
    {
    if (i>=1000000) i=0; 		//Wenn i=1000000 (entspricht einer Sekunde) dann fang eine neue Sekunde an
    if (i<= 500000) PORTC = (1<<PC0); //Mach 'ne halbe Sekunde die LED an
    else PORTC &= ~(1<<PC0); 	//Ne halbe Sekunde aus
    i++;
    TCNT1 = 0-16;	//Zähl' bis 16 => 1000000 mal pro Sekunde ein Interrupt
    }
    
    	
    /* //Durch mitzählen kein Fehler:
    ISR (TIMER1_OVF_vect)
    {
    if (i==1000) i=0; 		//Wenn i=1000 (entspricht einer Sekunde) dann fang eine neue Sekunde an
    if (i<= 500) PORTC = (1<<PC0); //Mach 'ne halbe Sekunde die LED an
    else PORTC &= ~(1<<PC0); //Ne halbe Sekunde aus
    i++;
    TCNT1 = 0-16000;	//Zähl' bis 16000 => 1000 mal pro Sekunde ein Interrupt 
    }	*/
    Wär' nett, wenn jemand mal darüber schaut.

    Danke,
    Stephan

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    16.12.2006
    Beiträge
    205
    Hallo

    also zuerst mal zu deiner Timer Einstellung. Was für ein AVR ist das denn? Bei dem Mega 8 wäre deine TCCR1B Einstellung z.B. "External clock source on T1 pin. Clock on rising edge"
    Außerdem würde ich nicht um eine Sekunde zu messen den Prescaler auf 1 stellen und dann noch so vorladen, dass man 1000000 Interrupts pro Sekunde hat. Es gibt hier irgendwo ein kleines Programm (rnAVR) damit kann man recht gut bestimmen, was man so als Prescaler und Vorladewerte nehmen kann.
    Ich würde das dann so machen: (für den Mega8, musst du dann übertragen)

    Code:
    int main(void) {
    
    DDRC |= (1<<0);
    PORTC &= ~(1<<0);
    
    TCCR1B |= (1<<CS12);          //Prescaler 256
    TCNT1 = 3036;                  //Vorladewert für den Timer
    TIMSK |= (1<<TOIE1);
    
    sei();
    }
    
    ISR(TIMER_OVF_vect) {
    PORTC ^= (1<<PC0);
    TCNT1 = 3036;
    }

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests