Ich möchte gerne einen Zähler realisieren, der mit möglichst hoher Frequenz läuft. Zum Beispiel mit der Taktfrequenz des µC. Ich möchte nämlich bestimmte Ereignisse der "CPU-Zeit" zuordnen können. Dazu braucht ich aber mindestens einen 32 bit breiten Zähler. Kann ich das so machen, daß ich einen 16 bit Hardware Zähler des AVR laufen lasse, und mit dem "Überlauf-Interrupt" einfach ein Word hochzähle? Mal angenommen, das geht... wie löse ich die zwei Probleme: 1. Wenn ich den aktuellen Zählerwert beim Eintritt eines Ereignisses zur späteren Verwendung "kopiere", kann ich das nur Byte für Byte machen. Was ist aber, wenn sich während des Kopierens der Zähler ändert? Zum Beispiel von 65535 auf 65536? Wenn mein Zähler mit der Taktfrequenz läuft, wird er sich ja zwangsläufig während des Auslesens ändern. 2. Wie erreiche ich eine Lösung für Punkt 1, ohne daß der Zähler durch diese Lösung einzelne Schritte überspringt. Das würde ja passieren, wenn ich die Interrupts während des Auslesens des Zählers sperre.
Mach es einfacher. Setzte zum Begin deiner Messung ein IO-Ausgangspin auf HIGH und am Ende auf Low. Mit einem Oszilloskop kann man wunderbar die Zeit messen. Ausserdem kann man das auch recht gut und genau simulieren, der Simulator zählt für dich die Takte. MfG Falk
Darf man fragen, was du machst, dass du Zeitpunkte mit einer derart hohen Auflösung definieren musst? Woher weißt du, wie lange es exakt (also auf den CPU-Takt genau) dauert, bis dein Programm vom Auslösen des Ereignisses an gerechnet überhaupt mitkriegt, dass etwas passiert ist? Wie gut hast du deinen Quarz thermisch stabilisiert, so dass die exakte Anzahl der Taktzyklen irgendeine Aussagekraft in Bezug auf die dadurch verstrichene Zeit erlaubt. Oder verwendest du eine exaktere Zeitbasis als einen Quarz? (Worauf ich mit den letzten Fragen hinaus will: Selbst wenn du auf die Quarzschwingung genau eine Zeitdauer abmesssen kannst, hilft dir das Ergebniss nicht viel. Ein 16Mhz Quarz schwingt nicht exakt auf 16000000.000 Hz. Gut, das könnte man noch ausmessen. Aber er verändert seine Frequenz auch mit der Umgebungstemperatur.) > kann ich das nur Byte für Byte machen. > Was ist aber, wenn sich während des Kopierens der Zähler ändert? > Zum Beispiel von 65535 auf 65536? Wenn mein Zähler mit der > Taktfrequenz läuft, wird er sich ja zwangsläufig während des > Auslesens ändern Ja klar. Zu allererst: Deine Überlegung bezüglich des Überlaufs ist so schon grundsätzlich korrekt. Wenn es sich um ein externes Ereignis handelt, könnte man mit dem Capture Input arbeiten, bei dem die Hardware den aktuellen Zählerstand umkopiert. Möchtest du aber dein Programm auf CPU-Takt Genauigkeit ausmessen, läufst du in ein Problem, das zb. Physiker haben, wenn sie in immer kleinere Dimensionen vorstossen: Irgendwann beeinflusst die Messung das zu messende System. In deinem Fall: Du kriegst ja den Timer auch nicht kostenlos. Das Setzen, Starten, Auslesen des Timers kostet auch CPU-Takte. Takte, die normalerweise vernachlässigbar sind, bei den Dimensionen die du dir aber vorstellst schon ins Gewicht fällt. Dennoch sollte man sich zuallererst die Frage stellen: Wie genau ist eigentlich "möglichst genau" und warum muss das so genau sein wie ich mir das vorstelle. Wie wirkt sich meine Messungenauigkeit im Ergebnis, das ich erhalten möchte, eigentlich aus?
Powermichi schrieb: > Mal angenommen, das geht... wie löse ich die zwei Probleme: > > 1. Wenn ich den aktuellen Zählerwert beim Eintritt eines Ereignisses zur > späteren Verwendung "kopiere", kann ich das nur Byte für Byte machen. > Was ist aber, wenn sich während des Kopierens der Zähler ändert? Zum > Beispiel von 65535 auf 65536? Wenn mein Zähler mit der Taktfrequenz > läuft, wird er sich ja zwangsläufig während des Auslesens ändern. > > 2. Wie erreiche ich eine Lösung für Punkt 1, ohne daß der Zähler durch > diese Lösung einzelne Schritte überspringt. Das würde ja passieren, wenn > ich die Interrupts während des Auslesens des Zählers sperre. Schön, daß Du die Probleme richtig erkannt hast. Die Lösung: Beitrag "AVR Timer mit 32 Bit" Peter
Zur Anwendung: Ich bekomme einen externen Interrupt von einem Timing-Generator, der zur GPS-Sekunde synchronisiert ist. Leider nur einmal pro Sekunde. Meine Anwendung macht Messungen und ich muß die Messungen einer definierten Zeit zuordnen. Statt jetzt eine PLL zu bauen etc., wollte ich einfach die CPU-Takte mitzählen, die seit dem Interrupt verstrichen sind. Die Auflösung ist sicher höher als die Genauigkeit, also unnütz, aber es erschien mir einfacher, so vorzugehen. Mit dem Code von Peter komme ich schonmal weiter, danke. Auch, wenn ich in Assembler schreibe (-n muß).
Weiter unten hat Peter auch sein LST-File (Assembler) gepostet.
Wenn es um ein externes Signal geht, dann nimmt man wenn möglich die Input-capture funktion. Damit kriegt man die unteren 16 Bits in Hardware direkt mit der Flanke. Wie gut die Ganuigkeit des GPS Signals ist hängt vom Empfänger ab, der Sekundenpuls kann aber schon sehr genau sein. Über einen kurze Zeit ist auch ein einfacher Quarz schon sehr stabil. Es ist damit gar nicht so sinnlos bis auf einen Taktzyklus ganu zu messen. Für eine Sekunde könnten auch 24 Bits schon reichen (bis 16 MHz Takt).
Input Capture geht nicht, da ich meinen Zählerstand zu internen Vorgängen abspeichern will. Der externe Interrupt setzt lediglich den Zähler zurück. Aber ich denke, mit den Tips komme ich ganz gut weiter.
Man muß den Zähler zur Syncronisation nicht zurücksetzen. Es reicht wenn man sich den Zählerstand merkt und dann später abzieht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.