Forum: Compiler & IDEs Atmega32 Pulsbreitenmessung 200ns


von Christian M. (moetown)


Angehängte Dateien:

Lesenswert?

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

von Christian M. (moetown)


Angehängte Dateien:

Lesenswert?

Und hier das Programm...

von hans (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Christian M. (moetown)


Lesenswert?

>>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

von Falk B. (falk)


Lesenswert?

@ 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

von Falk B. (falk)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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

von Stefan E. (sternst)


Lesenswert?

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.

von Christian M. (moetown)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.