Forum: Mikrocontroller und Digitale Elektronik Timer funktioniert nicht richtig?


von Tung N. (sumovd)


Lesenswert?

Hallo,

für meine Projekt benutze ich den Atmega16. Um einen Rechteckpuls mit 
einer Pulsbreite 10µs an pin PD4 zu erzeugen kommt der Timer0 zum 
Einsatz.
Die Idee ist folgendes: Ich betreibe den µC bei 8Mhz. Timer Vorteile 
8--> Clock Timer = 1Mhz. Der Pin PD4 wird zunächst auf High gesetzt, 
gleichzeitig wird der Timer gestartet und zählt bis 10 (entsprechend 
10µs), dann wird ein Interuppt ausgelöst, wobei der Pin wieder auf Low 
gesetzt.
Das Problem ist: ich habe den Puls mit einem Osciloscop gemessen. Was 
ich  an dem Pin rauskriege ist ein Puls mit einer Pulsbreite von ca. 100 
µs. Kann jemand mir das erklären? Liegt es daran, dass der Timer nicht 
rechtzeitig gestartet wird oder beim Interrupt wird das Programm 
verzögert?

Unten ist die C-Code als Funktion:
1
void trigger(void)
2
{ 
3
     DDRD|= (1<<PD4);
4
     PORTD |= (1<<PD4);
5
     //Der µC wird mit 8Mhz betrieben, Vorteile 8--> Clock Timer = 1Mhz
6
     TCCR0 = (1<<CS01);
7
     //Vergleichwert
8
     OCR0 = 10;
9
     //Output Compare Match interrupt aktivieren
10
     TIMSK = (1<<OCIE0);
11
     //Timer aktivieren
12
     TCNT0 = 0;
13
}
14
ISR (TIMER0_COMP_vect)
15
{
16
    //Timer stoppen
17
    TCCR0 = 0;
18
    //PIND4 auf Low setzen
19
    PORTD &=~(1<<PD4);
20
}

von Kai F. (kai-) Benutzerseite


Lesenswert?

ich weiß nicht wieso du überhaupt einen Rechteckimpuls bekommst...
du setzt in deiner ISR den Pin immer wieder auf Low, aber nicht mehr auf 
high.

von Steffen (Gast)


Lesenswert?

zu deinem Code:
1
 TCCR0 = (1<<CS01);
mit dieser Zeile aktivierst du den Timer 0 schon
1
 TCNT0 = 0;
hier setzt du den Timer 0 einfach nur zurück. Deswegen wird der 
Interrupt später ausgelöst.

versuche doch die Zeile mit dem Prescaler ganz nach unten zu setzen. 
Kurz davor solltest du den PIN an Port D setzen. Das würde ich einfach 
mal ausprobieren und mit dem Oszi nachmessen. Pass aber auch, wenn du 
die globalen Interrupts frei gibst.

von Johannes M. (johnny-m)


Lesenswert?

Betreib den Timer im CTC-Modus. Dann brauchst Du in der ISR nicht das 
TCNT0 zurückzusetzen. Außerdem ist es sinnvoll, so ein Signal über die 
Compare-Einheit per Hardware zu erzeugen (automatisches Umschalten des 
Pins OC0). Dann brauchst Du eigentlich gar keinen Interrupt mehr. Und 
10µs bekommst Du mit der obigen Version nie. Vom Setzen des Flags bis 
zur Ausführung von "PORTD &=~(1<<PD4);" vergeht auch eine ganze Weile 
(mindestens 10-15 Taktzyklen, also 1-2µs). Außerdem erfolgt das Setzen 
des Pins schon vor der ganzen Timer-Initialisierung. Da kommt noch mal 
einiges an Taktzyklen dazu (abgesehen davon, dass Du [wie Steffen schon 
sagte] das TCNT0 noch mal zurücksetzt).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.