Moin, ich hab eine Frage zum Counter des ATmega640. Was passiert, wenn ich den den Timer 2 mal hintereinander starte? Es geht bei mir um das Toggeln zwischen zwei IRS und in jede startet den selben Timer, je nachdem welche ISR zuerst ausgeführt wurde. Ich möchte ganz gerne die zeitliche Differenz bestimmen, mit den diese beiden ISRs ausgelöst wurden. Beispiel: ISR1: TCCR1B |= 0x01; variable1 = TCNT1; ISR2: //wird kurz nach der ISR1 ausgeloest TCCR1B |= 0x01; variable2 = TCNT1; Anschließend nehme ich die Differenz, je nachdem welche ISR zuerst ausgeführt wurde (minus der Zeit, die die Instruktionen zum starten der jeweils anderen ISR und das schreiben des Registerwertes in TCCR1B benötigen). Is wohl etwas unsauber, ich weiss. Aber funktioniert dieses Prizip generell oder wird der Timer beim zweiten Start zurückgesetzt? Wenns unverständlich ist, dann male ich gern ein Bild. :) Danke im Vorraus!!
Schau Dir deinen Code genau an, da steht nämlich die Antwort drin:
1 | TCCR1B |= 0x01; |
2 | ... |
3 | TCCR1B |= 0x01; |
Hier wird das Register TCCR1B mit 0x01 per ODER Funktion Verknüpft. Was macht die ODER Funktion mit den Bits? Ausgangszustand Timer gestoppt, Bit 0 = 0. Timer Starten: 0 ODER 1 = 1 Timer nochmal starten: 1 ODER 1 = 1 Das heisst, wenn Du den gleichen Befehl zweimal nacheinander ausführst, ist der zweite völlig Wirkungslos.
Du musst den Timer nicht in den ISRs starten. Einmal zu Beginn des Programms reicht. Die Anweisung
1 | TCCR1B |= 0x01; |
bewirkt nichts, wenn das Bit vorher schon gesetzt war. Der Counter wird dadurch nicht zurückgesetzt.
Fabian O. schrieb: > Einmal zu Beginn des > Programms reicht. Geht Leider nicht. Ich möchte eine genaue Differenzzeit bestimmen, welche ISR zu erst und welche als zweites ausgelöst wurde. Wenn ich den Timer ausserhalb der ISR starte, so gibt es bei 8 MHZ alle 125 ns * 2^16 = ca. 8,1 ms einen Überlauf. Wenn ich in die ISR springe, so kann der Zählerwert meinetwegen gerade bei 65000 sein und wenn die zweite ISR gestartet wurde bei wieder bei 100. Jetzt könnte ich die OVFs zählen, stimmt. Aber ich denke die 8,1 ms reichen mir aus. Mit einen größeren zeitlichen Versatz starten die beiden ISRs nicht voneinander, so dass ich den Timer erst innerhalb der ISR starten kann. Ich muss diesen in beiden ISRs starten, da ich nicht weiss, welche zu erst ausgelöst wird! :)
Weiss jemand, wie lange der interne Komparator des ATmege ca. braucht, bis eine ISR gestartet wird (nachdem die Differenzspannung am Eingang das Vorzeichen wechselt)? Hab da leider keine Angaben im Datenblatt zu gefunden. Auch nichts über den Offset.
Hi > so gibt es bei 8 MHZ alle 125 ns * 2^16 >= ca. 8,1 ms einen Überlauf. Wenn ich in die ISR springe, so kann der >Zählerwert meinetwegen gerade bei 65000 sein und wenn die zweite ISR >gestartet wurde bei wieder bei 100. Dein Code-Fetzen verhindert auch keinen Überlauf. Das Setzen des CS-Bits beeinflußt den Zählerstand des Timers nicht. Also kann der durchaus auch mal bei 65535 starten. MfG Spess
Der Code is schon noch etwas länger. Also jede ISR wird nur einmal ausgelöst, der zeitliche Unterschied ist <8 ms. Nachdem die zeitliche Differenz ermittelt wurde, wird der Zähler wieder zurückgesetzt und die beiden ISR können wieder auslösen. Eigentlich dürfte dann doch kein Überlauf eintreten, oder?
Bastoo schrieb: > Wenn ich in die ISR springe, so kann der > Zählerwert meinetwegen gerade bei 65000 sein und wenn die zweite ISR > gestartet wurde bei wieder bei 100. Macht ja nichts, die Differenz stimmt trotzdem. Allerdings musst Du wissen, welcher Wert vorher und welcher nachher war. Entweder speichst Du das in einer eigenen Variable, oder Du weißt, dass die Differenz unter 4 ms ist. Dann nimmst Du von beiden Möglichkeiten die kleinere. Aber wenn Du die Differenz nur einmalig ermitteln willst, geht es natürlich auch so, wie Du es machen willst. Ansonsten musst Du nach den beiden ISRs den Timer stoppen und den Zähler wieder auf Null setzen.
Super, danke euch! Habt ihr vielleicht noch eine Idee, wie ich an die technischen Daten vom AC des ATmega kommen kann?
Bastoo schrieb: > Fabian O. schrieb: >> Einmal zu Beginn des >> Programms reicht. > > Geht Leider nicht. Es geht praktisch immer. > so gibt es bei 8 MHZ alle 125 ns * 2^16 = ca. 8,1 ms einen Überlauf. OK. > Aber ich denke die 8,1 ms reichen mir aus. Na, dann ist doch alles in Butter! > Wenn ich in die ISR springe, so kann der > Zählerwert meinetwegen gerade bei 65000 sein ja, macht ja nix > und wenn die zweite ISR > gestartet wurde bei wieder bei 100. Auch ok. Wo liegt das Problem? > Jetzt könnte ich die OVFs zählen, stimmt. Nö. Wenn du dir sicher bist, dass du über die 8.1ms nie drüber kommen wirst, dann rechnest du einfach differenz = ende - start und kriegst bei 16 Bit unsigned Arithmetik immer das richtige Ergebnis raus. Selbst dann wenn der Timer zwischendurch einmalig übergelaufen ist. Diesen einen Overflow brauchst du überhaupt nicht berücksichtigen. > wird der Zähler wieder zurückgesetzt und die Spars dir. Starte den Timer beim Programmstart und lass ihn laufen. Dieses ganze Gemurkse mit Timer starten/stoppen/zurücksetzen ist alles den Aufwand nicht wert.
Bastoo schrieb: > Fabian O. schrieb: >> Einmal zu Beginn des >> Programms reicht. > > Geht Leider nicht. Ich möchte eine genaue Differenzzeit bestimmen Wie genau? Sobald du in den Bereich kommst, dass deine Genauigkeitsanforderungen in die Größenordnung von ca. (ich würde mal sagen) 10 Takzyklen des µC kommen, wirds haarig. Denn vom Auslösen des Interrupts bis zum Bearbeiten vergehen ein paar Takte, die aber nicht immer gleich viele sind. Das kann man noch mit einem Input Capture lösen. Aber sobald die zeitlichen Unterschiede zwischen den Flanken sich ebenfalls in diesem Bereich bewegen, dann hilft dir auch der Capture nichts mehr, weil du dann nicht mehr feststellen kannst, welche Flanke zuerst kam bzw. das Capture Register nicht mehr schnell genug auslesen kannst. Da geht nur noch externe Hardware oder ein wesentlich schnellerer Prozessor. Die Forderung nach "möglichst genau" ist * meistens nicht sinnvoll, * nur mit erheblichem Hardwareaufwand zu erreichen * dann allerdings nicht zu bezahlen und * meist auch gar nicht notwendig
Ich führe in jeder ISR eine Subtraktion durch. Ungefähr so: ISR1: TCCR1B |= 0x01; variable1 = TCNT1; (sprung in ISR2, wenn ISR2 nicht als erstes ausgelöst wurde. Zeitpunkt <8 ms) Differenz = variable2 - variable1; ISR2: //wird kurz nach der ISR1 ausgeloest TCCR1B |= 0x01; variable2 = TCNT1; (sprung in ISR1, wenn ISR1 nicht als erstes ausgelöst wurde. Zeitpunkt <8 ms) Differenz = variable1 - variable2; Wenn ISR1 zuerst auslöst, die Variable 1 jetzt 65000 ist und die Variable2 aber 100, dann bekomme ich doch einen falschen wert raus. auch bei unsigned, oder nicht? Es wird ja gerechnet 100-65000.
Ja, so genau muss es garnicht sein. Ich hab über den Assambler Code schon geschaut, welche Instruktionen zwischen den ISRs ausgeführt werden. Diese ziehe ich natürlich nochmal vom Gesamtwert ab.
Bastoo schrieb: > Wenn ISR1 zuerst auslöst, die Variable 1 jetzt 65000 ist und die > Variable2 aber 100, dann bekomme ich doch einen falschen wert raus. Nö. > auch > bei unsigned, oder nicht? Es wird ja gerechnet 100-65000. Ja und. das Ergebnis von 100-65000 (16 Bit unsigned gerechnet) ist 636 Und genau so viele Zählschritte liegen auch zwischen 65000 und 100
Bastoo schrieb: > Ja, so genau muss es garnicht sein. Nochmal: Wie genau? Spezifizier das in Form einer Zahlenangabe. Sonst reden wir aneinander vorbei. Geht es um µs, um ms, um Sekunden, Stunden, Tage? Wieviele µs? Wenn du bei 16Mhz auf 1/10 µs genau messen willst, dann ist wird das Verfahren anders aussehen, als wie wenn dir ein Jitter von 1µs egal ist. Was, exakt, willst du messen, dass du eine Zeitdifferenz mit einer Genauigkeit von 1 Millionstel Sekunde (oder noch besser) feststellen können musst? Und welches ist die kleinste Zeitdiffernz, die in deiner Messung PRAKTISCH gesehen vorkommen wird?
Die kleinste Differenz, die ich bisher gemessen habe (die Instruktionen zwischen den beiden Zeitmessungen abgezogen), beträgt 8 µs. Die größte Zeitdifferenz beträgt 4000 µs.
Bastoo schrieb: > Ist eine Genauigkeit von 5-10 µs möglich? Das sind 80 bis 160 CPU/Timertakte. Daher: Ja, das ist kein Problem. Führ beide Signale mittels Dioden-Or zusätzlich zusammen auf den Input Capture und in der ISR holst du dir das Capture Ergebnis und siehst an den regulären Pins nach, welcher Pin das Capture Ereignis ausgelöst hat. Du brauchst keine Code-Laufzeiten berücksichtigen oder Interrupt Latenzen einrechnen. Der Timer Input Capture merkt sich den Zählerstand, an dem das Ereignis eingetreten ist. Die Minimal-Zeit Differenz ergibt sich aus dem Zeitbedarf, den dein Programm braucht, bis es sich das Capture Ergebnis abholen kann. Das ist das Minimum, unter welches du mit dem Input Capture nicht kommst. Dafür ist das komfortabel und Straight Forward zu programmieren.
:) Danke Dir Karl! Btw. ich arbeite mit 8 MHz und die Platine ist schon fertig. Das mit der Zeitdifferenzmessung war nicht unbedingt nötig und wurde, da noch etwas Zeit für das Projekt über war, erst später realisiert. Daher ist es auch nicht unbedingt ein "must-have" im Projekt. Da ich es aber implementiert habe, interessiert mich die Genauigkeit doch schon ein wenig. Aber wenn die Ungenauigkeit < 10 µs ist, dann bin ich zufrieden.
@ Bastoo (Gast) >Weiss jemand, wie lange der interne Komparator des ATmege ca. braucht, >bis eine ISR gestartet wird (nachdem die Differenzspannung am Eingang >das Vorzeichen wechselt)? Ist wie ein normaler externer Interrupt. Der Einsprung dauert 4 Takte. > Hab da leider keine Angaben im Datenblatt zu >gefunden. Auch nichts über den Offset. Siehe Datenblatt "Analog Comparator Input Offset Voltage", max. 40mV. MFG Falk
Bastoo schrieb: > :) Danke Dir Karl! > > Btw. ich arbeite mit 8 MHz und die Platine ist schon fertig. OK. Also 40 bis 80 µC Takte. Sollte immer noch reichen, um eine schöne Capture Auswertung zu machen, wenn du die Hardware noch zubauen könntest. Sonst eben mit den Interrupts. Geht natürlich auch, wenn auch nicht so taktgenau wie mit dem Capture. Der Vorteil vom Input Capture besteht nun mal darin, dass die Hardware den exakten Zählerstand festhält, an dem die Flanke im Signal kam. D.h. wenn dein µC danach ein paar Takte braucht, bis er dann endlich soweit ist ein Register vom Timer auszulesen, dann spielt das keine große Rolle, weil du ja auf diesen, vom Timer selbst festgehaltenen Wert zugreifst und dir den holst. Und der ist genau der Wert, an dem die Flanke per Hardware registriert wurde.
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.