Forum: Mikrocontroller und Digitale Elektronik ATMega16 ICP


von Bob (Gast)


Lesenswert?

Sers Leute,
ich programmiere in C mit Codevision. Der ATMega läuft mit 16MHz.
Nun möchte ich den ICP nutzen, indem ich bei fallender Flanke den
Zähler rücksetze und auf steigende Flanke umstelle (TCCR1B=0xC1). Kommt
die steigende Flanke, wird der ICR-Register ausgelesen und gespeichert
(ICRH zuerstm, dann low), dann wieder auf fallende Flanke umgestellt
(TCCR1B=0x81).
Wenn ich nun zum Test einen Low-Pegel von 90µs anlege, so müsste ich im
ICR-Register so nen ungefähren Wert von 1440 haben. Mein tatsächlicher
(gemessener) Wert ist jedoch viel niedriger (so ca.190).
Die Ausgabe (ans Termianl) findet in einem anderen Timer statt.
Lediglich habe ich noch eine Kontrollfunktion in dieser ICP-ISR
eingebaut, indem ich einen PIN für die Dauer der ISR auf 1 setze. Somit
kann ich am OSZI beobachten, ob die ISR überhaupt durchlaufen wird. ->
Ja sie wird.
Meine Frage:
Wieso habe ich so eine große Differenz zwischen theoretischem und
gemessenen ICR Wert?

von Olaf K. (Gast)


Lesenswert?

>wird der ICR-Register ausgelesen und gespeichert (ICRH zuerstm, dann
low)

Datenblatt S.90: "... For a 16-bit read, the Low byte must be read
before the High byte."

Den ICP-Interrupt würde ich übrigens nicht dazu nutzen, den Timer
rückzustellen, denn dadurch geht der Vorteil der Clockgenauigkeit
verloren. Wann genau der ICP-Interrupt abgearbeitet (und damit der
Timer rückgestellt) wird, hängt von vielen Faktoren ab, z.B. ob gerade
ein anderer Int bearbeitet wird oder zeitweilig ein cli gesetzt wurde,
oder ob der ICP-Int gerade während eines Multi-Cycle-Befehls auftrat
(z.B. JMPs oder Branches), oder vielleicht auch vom Sleep-Modus.

Der ICP-Wert wird dagegen zusammen mit dem ICP-Flag genau bei der
betreffenden Flanke (bzw. mit Noise Canceler ein paar Takte später)
gespeichert, und wann man ihn dann per Interrupt abholt und
weiterbearbeitet, ist nebensächlich.

Normalerweise speichert man den ersten ICP-Wert (z.B. den bei fallender
Flanke) ab, läßt den Timer weiterlaufen bis zur steigenden Flanke (= 2.
ICP-Wert) und subtrahiert den 1. vom 2. Wert, das geht auch über die
$FFFF-Grenze hinaus (in asm sind das nur 2 Befehle, in C dürfte es mit
unsigned int gehen).
Überläufe erkennt man mittels Compare-Match-Interrupt, d.h. beim ersten
ICP-Int wird der Counter ausgelesen und direkt als Compare-Wert
gespeichert (bei Nutzung des Prescalers vorher was abziehen, sonst wird
der Comp-Int sofort ausgelöst).

MfG Olaf

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.