Hallo Habe ein Problem bei der Messung einer Pulsbreite eines digitalen Signals (siehe Anhang) mit der Input Capture Funktion. Bei der Messung wird ein Atmega32 mit 17,1776MHz eingesetzt. Die zu messenden Pulsbreiten variieren zwischen 200ns und 5000ns. Die zwei aufeinanderfolgenden Pulsbreiten sollen gemessen und die Zeiten anschließend voneinander subtrahiert werden. Falls das Ergebnis Null ist, dann ist das Signal OK. Ist es ungleich Null, soll eine LED aufleuten Da die Taktfrequenz 17,1776MHz beträgt, sollte die Länge eines Takts circa 59ns betragen und für einen Vergleich ausreichend sein. Das beigefügte Programm misst die richtigen Zeiten bei Pulsbreiten größer 2000ns Sekunden, bei Werten kleiner 2000ns wird erst die übernächste Flanke wieder detektiert. Woran kann das liegen, dass die nächste Flanke übersehen wird? Habe auch schon ein Rechtecksignal von einem Funktionsgenerator nachgemessen, bei T=4000ns misst der Atmega32 eine Pulsbreite von 2000ns, was ja OK ist. Bei einer Periodendauer von 3000ns wird jedoch eine Pulsbreite von 4500ns gemessen, anstatt 1500ns. Theoretisch sollten ja Pulsbreiten bis 200ns messbar sein oder lieg ich da falsch? Das verwendete Programm befindet sich im Anhang, es sind jedoch nur die betreffenden Funktionen enthalten um Platz zu sparen. MfG Christian
Schau dir mal an was dein Compiler aus dem Interruptaufruf macht! Die erste Flanke ist OK, aber bis er von da zurück ist, einen Programm- befehl abgearbeitet ist und er wieder im Interrupt ist wurde bereits die 3 (oder noch spätere) Flanke detektiert und der Wert der 2 Flanke überschrieben. Hier hilt nur echtes selber warten ohne Interrupt oder Asembler. Gruß hans
@ Christian Moschner (moetown) >Bei der Messung wird ein Atmega32 mit 17,1776MHz eingesetzt. >Die zu messenden Pulsbreiten variieren zwischen 200ns und 5000ns. Ganz schön wenig! >Da die Taktfrequenz 17,1776MHz beträgt, sollte die Länge eines Takts >circa 59ns betragen und für einen Vergleich ausreichend sein. EIN Vergleich ja, der Prozess als solcher braucht aber WESENTLICH mehr Takte. >Das beigefügte Programm misst die richtigen Zeiten bei Pulsbreiten >größer 2000ns Sekunden, bei Werten kleiner 2000ns wird erst die >übernächste Flanke wieder detektiert. >Woran kann das liegen, dass die nächste Flanke übersehen wird? Schon mal überlegt, dass in 2000ns=2us bei ~17 MHz gerade mal 34 Takte für die CPU bleiben. Und in der Zeit, soll deine ISR kompltett abgearbeitet werden? Hmm? >Theoretisch sollten ja Pulsbreiten bis 200ns messbar sein oder lieg ich >da falsch? Du liegst falsch. Der AVR kann ein kurzen Puls, der mind. 2 Takte lang ist, sicher erfassen. Das mach die ICP Funktion in Hardware. Wenn du aber die Zeitdifferenz zwischen zwei Flanken messen willst, muss das die CPU per Software machen. Dort liegen die minimal erfassbaren Zeiten WESENTLICH höher. Deine Funktion kann man nur in reiner Hardware per CPLD lösen. Oder mit einem uC, der zwei ICPs hat. >Das verwendete Programm befindet sich im Anhang, es sind jedoch nur die >betreffenden Funktionen enthalten um Platz zu sparen. cli() in einer ISR ist recht sinnfrei. MFG Falk
>>Da die Taktfrequenz 17,1776MHz beträgt, sollte die Länge eines Takts >>circa 59ns betragen und für einen Vergleich ausreichend sein. >EIN Vergleich ja, der Prozess als solcher braucht aber WESENTLICH mehr >Takte. Ja ein vergleich reicht aus, deshalb auch das cli() in der ISR, damit diese nicht noch einmal ausgeführt wird und der Prozessor Zeit hat sich um die Auwertung zu kümmern und andere Funtionen auszuführen. Nach diesem Vergleich vergehen 5 Sekunden bis zum nächsten Signal mit anderen Pulsbreiten. >>Das beigefügte Programm misst die richtigen Zeiten bei Pulsbreiten >>größer 2000ns Sekunden, bei Werten kleiner 2000ns wird erst die >>übernächste Flanke wieder detektiert. >>Woran kann das liegen, dass die nächste Flanke übersehen wird? >Schon mal überlegt, dass in 2000ns=2us bei ~17 MHz gerade mal 34 Takte >für die CPU bleiben. Und in der Zeit, soll deine ISR kompltett >abgearbeitet werden? >Hmm? Bin davon ausgegangen das das Register sichern einen Takt benötigt und das Umschalten der Flankendetection ebenfalls einen Takt braucht. Zum rechnen kann sich die CPU ja dann Zeit lassen, da alle Interrupts deaktiviert sind. MfG Christian
@ Christian Moschner (moetown) >Ja ein vergleich reicht aus, deshalb auch das cli() in der ISR, damit Ist dennoch Unsinn, weil a) die Interrupts scho aus sind b) das reti am Ende der ISR diese cli() unwirkasm macht Wenn du den ICP Interrupt auschalten willst, dann über das Steuerbit im zugehörigen Register. >Nach diesem Vergleich vergehen 5 Sekunden bis zum nächsten Signal mit >anderen Pulsbreiten. Wird trotzdem knapp. IN ASM vielleicht machbar, in C kaum. >Bin davon ausgegangen das das Register sichern einen Takt benötigt und Geht schom la gar nicht, da es ein 16 Bit Register ist. Und C hat num mal einen gewissen Overhead. >das Umschalten der Flankendetection ebenfalls einen Takt braucht. Zum Du bist nicht in ASM ;-) MFG Falk
Man könnte einen Trick anwenden. Das Signal auf den ICP UND INT0 legen. INT0 triggert auf steigende Flanke, ICP auf fallende. Kommt nun die erste steigende Flanke, wird INT0 ausgelöst. Die CPU speichert Timer1 in einer Variablen. Die Verzögerung bis dorthin ist konstant. Triff nun währenddessen der ICP Interrupt auf, ist das egal, die Hardware speichert die Zeit des ICP und die CPU kann dann "langsam" das Ergebnis abholen. Damit könnte man die minimal messbare Pulsbreite bis an die technische Auflösungsgrenze von 1 Takt drücken. Allerdings muss die Pause zwischen den Pulsen reichen, um beide ISRs abzuarbeiten. Das kann man dan auch in C erledigen, ganz ohne ASM. MFG Falk
Falk Brunner wrote: > Damit könnte man die minimal messbare Pulsbreite bis an die technische > Auflösungsgrenze von 1 Takt drücken. Nicht ganz, denn das: > Die Verzögerung bis dorthin ist konstant. stimmt nicht. Die Zeit vom Interruptereignis bis zur Ausführung des Interruptcodes kann um ein paar Takte variieren.
@ Stefan Ernst (sternst) >stimmt nicht. Die Zeit vom Interruptereignis bis zur Ausführung des >Interruptcodes kann um ein paar Takte variieren. Auch das kann man umgehen. Man versetze die CPU in den Sleep Mode Idle, dann ist die Interrupt-Reaktionszeit konstant. MFg Falk
Falk Brunner wrote: > Auch das kann man umgehen. Man versetze die CPU in den Sleep Mode > Idle, dann ist die Interrupt-Reaktionszeit konstant. Interessant, da habe ich noch gar nicht dran gedacht, danke.
@ hans Hab mir mal den ASM Code angeschaut... schon für das sichern und zurückschreiben der Register in den stack werden 12 Takte benötigt. @ Falk Brunner (falk) Ich werde mal den Trick mit dem Int0 probieren, die Idee ist klasse, danke.
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.