Forum: Mikrocontroller und Digitale Elektronik Fragen zu 16-bit Timer/Counter 1


von michi (Gast)


Lesenswert?

Hallo!
ich wollte den 16-bit Timer verwenden um die Dauer eines Signals zu 
bestimmen.
Dazu wird ein Interrupt ausgelöst, wenn sich der Pegel an einem Pin 
ändert und in der Interrupt Routine soll der Timer gestartet werden. 
Wenn sich der Pegel wieder ändert, soll der Timer ausgelesen und 
zurückgesetzt werden.
Ich benutze einen Atmega 328P und zum programmieren einen Dragon.
Wenn ich über DebugWire das Programm ablaufen lasse, bleibt der Wert in 
TCNT1 aber bei null. Der Timer scheint also nicht gestartet worden zu 
sein.
Soweit ich das Datenblatt verstanden habe muss man um den Timer zu 
starten eigentlich nur folgendes eingeben:
TCCR1B = ((1<<CS12) | (1<<CS10));  //start timer prescaler=1024
Für eine kurze Hilfe wäre ich dankbar.
Grüße,
Michi

von ptc (Gast)


Lesenswert?

Mach das mit dem eingebauten Input-Capture, das ist zum Messen da!

von michi (Gast)


Lesenswert?

ich habe das zu messende Signal an PCINT7 angeschlossen. Das Input 
Capture kann man doch nur mit ICP1 verwenden, oder?
Umbauen kann ich die Schaltung nicht mehr.
Danke schonmal für die schnelle Antwort!

von STK500-Besitzer (Gast)


Lesenswert?

michi schrieb:
> Dazu wird ein Interrupt ausgelöst, wenn sich der Pegel an einem Pin
> ändert und in der Interrupt Routine soll der Timer gestartet werden.
> Wenn sich der Pegel wieder ändert, soll der Timer ausgelesen und
> zurückgesetzt werden.

Lass den Timer einfach so laufen - wie man es auch beim ICP macht.
Die erste Aktion beim Auftreten des PCINT liest du das Timer-Register in 
eine Variable ein und guckst anschliessend nach dem Pegel des Pins.
Danach berechnest du je nach Flanke die Pulslänge.

michi schrieb:
> ich habe das zu messende Signal an PCINT7 angeschlossen. Das Input
> Capture kann man doch nur mit ICP1 verwenden, oder?
> Umbauen kann ich die Schaltung nicht mehr.

schön blöd...

von STK500-Besitzer (Gast)


Lesenswert?

Andere Sachen (z.B. UART) sollte man dann aber nicht mehr unbedingt per 
Interrupt abarbeiten, da das zu einem Jitter oder anderen Messfehlern 
führen kann.

von ptc (Gast)


Lesenswert?

Dann löte einen Draht zu deinem ICP rüber. Sowas kann man beim 
Prototypenaufbau schonmal machen.

Oder nächstes mal: Zuerst denken: Was brauch ich und dann den Schaltplan 
machen, und nicht zuvor alles irgendwie hinwursteln und sich dann 
wundern dass man Probleme bekommt.


Sonstige Möglichkeit: Pinchangeinterrupt nehmen und abschätzen. wird 
aber sehr ungenau.

von michi (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Lass den Timer einfach so laufen - wie man es auch beim ICP macht.
> Die erste Aktion beim Auftreten des PCINT liest du das Timer-Register in
> eine Variable ein und guckst anschliessend nach dem Pegel des Pins.
> Danach berechnest du je nach Flanke die Pulslänge.

so hatte ich es auch eigentlich vor zu machen, aber wie gesagt bekomme 
ich den Timer nicht zum laufen. Eigentlich müsste er doch loslaufen, 
wenn ich im TCCR1B den Prescaler Wert festlege, oder?
Den aktuellen Zählerstand müsste ich dann in TCNT1 auslesen können.
Stimmt das soweit?

von Vuvuzelatus (Gast)


Lesenswert?

>Eigentlich müsste er doch loslaufen,
>wenn ich im TCCR1B den Prescaler Wert festlege, oder?

Ja.

>Den aktuellen Zählerstand müsste ich dann in TCNT1 auslesen können.

Ja.

Bist Du sicher, dass die Zeile "TCCR1B = ((1<<CS12) | (1<<CS10))" auch 
ausgeführt wird?

Wartest Du lange genug bis zur Abfrage von TCNT1? Bei Prescaler 1024 
bleibt TCNT1 während der ersten 1024 Taktzyklen natürlich noch auf 0, 
und wechselt dann erst auf 1.

Hast Du was mit dem PRR (Power Reduction Register) gemacht, z. B. T/C1 
abgeschaltet?

Deine Controller-Definitionsfiles sind die für den Atmega 328P?

von michi (Gast)


Lesenswert?

ich habe mal ein kleines Testprogramm geschrieben. Hier müsste doch 
eigentlich die LED an PIND7 blinken, oder?

#include <avr/io.h>
int main(){
  TCCR1B = ((1<<CS12) | (1<<CS10));        //start timer prescaler=1024
  DDRD|=(1<<PIN7);
  uint16_t cnt=0;
  while (1){
    cnt=TCNT1;
    if (cnt>=2000){                        //check timer
      PORTD^=(1<<PIN7);                    //toggle LED pin
      TCNT1=0;                             //reset timer
    }
  }
}

von michi (Gast)


Lesenswert?

habe noch ganz vergessen dir auf deine Fragen zu antworten:

Vuvuzelatus schrieb:
> Hast Du was mit dem PRR (Power Reduction Register) gemacht, z. B. T/C1
> abgeschaltet?
>

Nein, daran habe ich nichts verändert.

> Deine Controller-Definitionsfiles sind die für den Atmega 328P?
ja.

die restlichen Fragen müssten aus dem Code klar werden.
Danke für die Hilfe!

von Vuvuzelatus (Gast)


Lesenswert?

Das Prog funzt bei mir sowohl im Simulator (AVR Studio) als auch real 
(Mega8 auf STK500). Hab grad nen 16 MHz-Quarz drinstecken ==> 
Outputfrequenz 16MHz  1024  2000 / 2 = 3.9 Hz, und so schnell blinkt 
die LED an PD7 auch tatsächlich vor sich hin.

Und nu?

von --- -. (bomibob)


Lesenswert?

Vielen Dank für's testen...bin jetzt ein Bisschen verwundert, aber jetzt 
weiß ich wenigstens, dass es nicht am Programm liegt.
Dann mach ich mich mal auf Fehlersuche.
Hast mir auf jeden Fall weitergeholfen.
Falls dir noch einfallen sollte woran es noch liegen könnte, bin ich für 
Hilfe immer dankbar.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

michi schrieb:
> ich habe das zu messende Signal an PCINT7 angeschlossen. Das Input
> Capture kann man doch nur mit ICP1 verwenden, oder?

Nein. Da geht viel mehr, zumindest wenn nicht gleichzeitig der ADC 
verwendet wird. Schau einfach mal ins Datenblatt, wie man den InCapt 
füttern kann. Das geht zB auch über den Analog-Comparator oder den 
Input-MUX des ADC.

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.