Probleme mit Timer

Gast #2136096
Lesenswert?

Ich will mit einem Mikrocontroller ATMega32 90 Sekunden abwarten.

Das soll mit dem 8-Bit Timer gelöst werden.

Folgedermaßen hab ich mir das überlegt:

Taktfrequenz: 8MHz

Prescalor 1024 -> Auflösung 128µs

25ms/128µs = 195 -> 255-195 = 60 (von hier muss der 8-Bit-Timer 
hinaufzählen)

Mit einem Overflowinterrupt wird dann gezählt.

Getestet hab ich es, indem ich mit einem Tastendruck eine LED 
einschalte, die dann nach der entsprechenden Zeit wieder ausgehen 
sollte. Mein Problem ist allerdings, dass diese Zeit nicht mit der 
Berechnung überein stimmt. Die LED geht ca. 10 Sekunden zu früh aus.

Hier der Code:
------------------------------------------------------------------------ 
--
#define F_CPU 8000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/delay.h>

int Zeit = 0;

void InitPort() {
  PORTB = 0x01;
  DDRB = 0x01;
}

void InitInterrupt() {
  TIMSK |= (1<<TOIE0); // Owerflow Interrupt enabled
  sei(); // Interrupts enablen
}

void InitTimer() {
  TCCR0 = (1<<CS02) | (1<<CS00); // Prescalor: 1024 (CS02, CS01, CS00 => 
101)
  TCNT0 = 60;   // Von 60 wird aufwaerts gezaehlt
}

ISR(TIMER0_OVF_vect) {
  Zeit ++;  // globale Variable wird erhöht
  if (Zeit >=3600) {  // 90 * 40ms
    PORTB = 0x01; // LED aus
    Zeit = 0;
  }
  TCNT0 = 60;
}

int main () {
  InitPort();
  InitTimer();
  InitInterrupt();
  while(1) {
    if (!(PINB & (1<<PB4))) {    // Tastendruck
      Zeit = 0;
      PORTB = 0x00;        // LED an
    }
  }
return 0;
}
------------------------------------------------------------------------ 
---

Wär toll, wenn mir jemand erklähren könnte, was ich da falsch mache.

lg
Johannes
#2136364
Lesenswert?

Johannes schrieb:
> CTC

C lear T imer count on C ompare match

Der Timer hat eine Vergleicher-Einheit in Hardware. Jedesmal, wenn ein 
Taktimpuls kommt, wird der Zählerstand erhöht und gleichzeitig mit einem 
Register verglichen. Bei Übereinstimmung wird, sofern gewollt, ein 
Interrupt ausgelöst und der Zählerstand in Hardware zurückgesetzt.

Die Hardware erledigt also alles bis hin zur Interruptauslösung, wenn 
die entsprechenden Register richtig gesetzt sind. Nur um die 
Interrupt-Routine/-Behandlung musst du dich dann kümmern.

mfg mf
#2143946
Lesenswert?

Jannis C. schrieb:
> muss man sie als Globale Variable
>
> ausweisen ->volantile.

Nicht ganz. Global sind alle Variablen, die ausserhalb der Funktionen 
deklariert werden. Diese Variable bekommt dann eine feste Speicherstele 
im RAM (Heap).

Damit der Compiler jedesmal, nachdem die Variable in einer Funktion 
verändert wurde, diese auch wieder in die Speicherstelle zurück 
schreibt, wird diese mit "volatile" spezifiziert. Sonst kann es 
passieren, daß der Compiler die Variable in der Funktion einfach 
wegoptimiert.

mfg.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren