Forum: Mikrocontroller und Digitale Elektronik Problem mit Timer und Input Capture


von Kai H. (Gast)


Lesenswert?

Moin!

Habe ein Problem mit dem Input Capture und den Timern beim ATMega8
(Takt 4 Mhz).

Folgendes soll ablaufen:

In einem Highsignal treten in mehr oder weniger regelmäßigen Abständen
Clockimpulse auf, und zwar als Lowpegel für ca 50 us. Diese versuche
ich per Input Capture auf falling edge zeitmäßig zu erfassen und dann
diesen Zeitwert an den Timer 2 zu übergeben, damit dieser seinerseits
einen Output Compare Match erzeugen kann. Der Vorteiler ist so gewählt,
daß es bei der Übergabe von 16 auf 8 bit keine Probleme geben sollte.
Leider funktioniert diese Auswertung überhaupt nicht. Mal geht es für
einige Takte, dann gerät der Timerwert wieder völlig außer Kontrolle.
Habe mittlerweile so ziemlich alles versucht, Auswertung direkt,
Auswertung über zwei Captures und Übergabe der Differenz, Einsatz des
Noisecancel....immer mit unbrauchbaren Ergebnissen.

Mache ich hier irgendwo einen Denkfehler, oder ist der Impuls zu kurz,
als das er vom Mega8 vernünftig erkannt wird?

Vielleicht kann mir jemand einen Denkanstoß geben?

Vielen Dank!

Kai

von crazy horse (Gast)


Lesenswert?

Zeile 24.

von Dirk (Gast)


Lesenswert?

Hi,

am besten postet du mal dein Prg damit man ein Moeglichen Fehler
entdecken kann.

50µs ist extrem lang daran sollte es nicht liegen.


mfg

Dirk

von Kai H. (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal die ISRs und Timer Einstellungen!

von Kai H. (Gast)


Lesenswert?

Oh, und die Var wechsel hieß vorher zaehler, daran liegt es also nicht,
war in der Version nur noch nicht geändert! ;o)

von crazy horse (Gast)


Lesenswert?

ein paar Sachen fallen mir auf:
ein direkter Fehler:
TCNT1L=0;
TCNT1H=0;

das geht nicht, nur andersherum, erst H, dann L schreiben, beliebter
Anfängerfehler.
Beim Lesen hast du es richtig gemacht, erst L, dann H.

Am besten benutzt du direkt den 16bit-Zugriff, damit ersparst du dir
diese Probleme und auch das Addieren mit shift.
statt:
templ=ICR1L;
temph=ICR1H;
capture1=templ+(temph<<8);

schreibst du einfach:
capture1=ICR1;

ebenso
TCNT1=0;

Ansonsten: du ermittelst ein 16bit-Ergebnis, überträgst aber nur den
low-Teil davon an OCR2? Ist das so gewollt?
Was willst du letztendlich mit demProgramm bezwecken?

von Kai H. (Gast)


Lesenswert?

@crazy horse:

zunächst mal danke für Deine Antwort, das mit dem 16 bit access habe
ich eingebaut, mußte bloß erstmal die header-Datei umändern, weil
standardmäßig bei Codevision das nicht mit drin ist. Dort steht nur
ICR1H und L. Hat aber leider auch nicht zum Erfolg geführt.

Was das Programm am Ende bewirken soll ist Folgendes: Ich benötige
zwischen den Clocksignalen, die einen ext. Interrupt auslösen, mittig
einen weiteren Interrupt. Dafür will ich ständig die Zeit überwachen,
die zwischen den Clocks vergeht, und in der Hälfte der Zeit per compare
match den Interrupt auslösen. Manchmal funktioniert diese Zeitnahme auch
ein paar Takte lang, dann aber sieht man auf dem Oszilloskop wieder
völligen Wirrwarr, wo die Abstände wieder überhaupt nicht mehr stimmen.
Als würde ein Timer überlaufen o.ä., aber das kann ja eigentlich nicht
sein, denn dafür setze ich ja den Timer extra wieder auf Null zurück.
Daß ich einen 16 bit Wert an einen 8 Bit-Timer übergebe ist mir klar,
aber auch das dürfte eigentlich unkritisch sein, denn bei
Clockabständen von etwa 2ms hat der Zähler eh nur bis ca. 130 gezählt,
wenn ich nicht irre.
Ich drehe mich hier seit einer Woche echt im Kreis und komme nicht
weiter...

von crazy horse (Gast)


Lesenswert?

Hm, und warum benutzt du dafür nicht den OCR1x des Timer1? Ich würde den
Timer komplett durchlaufen lassen.

interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
static unsigned int capture_bak;  //letzter ICP-Wert
OCR1A=(ICR1-capture_bak)>>1;        //halbe Zeit zwischen letzter und
dieser Messung
capture_bak=ICR1;   //speichern für nächste Differenz
}

von crazy horse (Gast)


Lesenswert?

hm, Fehler drin:
OCR1A=ICR1+(ICR1-capture_bak)>>1;

hoffentlich stimmts jetzt :-)

von Kai H. (Gast)


Lesenswert?

Meinst Du mit Timer komplett durchlaufen lassen den Mode Top=0xFFFF?
Müßte man nicht den Timer CTC laufen lassen, also bei OCR1 zurück auf
Null? Denn sonst haut das doch mit der Zeit zwischen den Clocks nicht
hin, oder?

von crazy horse (Gast)


Lesenswert?

ja, meine ich, komplett durchlaufen lassen, kein CTC, kein stoppen, kein
reset.

Bsp:
1.Messung :0x2000
2.Messung :0x3000

Differenz=0x1000, davon die Hälfte 0x800, also setzt du OCR auf 0x3800,
da kommt dann der OCR-Int zwischen diesem und dem nächsten ICP-Ereignis
(falls die Impulse halbwegs konstanten Abstand haben).
Auch ein zwischenzeitlicher Überlauf ist kein Problem:

1.Messung: 0xf000
2.Messung: 0x1000
Differenz (mit unsigned int!) =0x2000

und auch dann klappts:
1.Messung: 0xf000
2.Messung: 0xfff0

Differenz 0xff0, davon die Hälfte 0x7F8, addiert zu 0xfff0=0x07e8 als
neuer OCR-Wert.

von Kai H. (Gast)


Lesenswert?

Vom Ansatz her gebe ich Dir völlig recht, stimmt, so müßte es
theoretisch laufen. Leider meint aber der Mega8, daß er sich deshalb
noch lange nicht so verhalten muß! :-(
Ich habe in der Zeit eines Interrupts vom Timer bereits 5 neue
Clockimpulse.
Habe sogar schon den Controller gewechselt, um auszuschließen, daß der
eine Macke hat!

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.