PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zündstroboskop und (mal wieder) delay_ms/us



VictimOfMyOwn
11.05.2006, 16:49
hi ho...

versuchsaufbau (zum verständnis):

elektromotor mit lochscheibe und gradskala. gabellichtschranke gibt ihr signal an INT0 weiter und lässt beim interruptaufruf eine LED "blitzen" welche auf die gradskala gerichtet ist.

µC ist ein atmega8 mit 16mhz quarz. als software verwende ich avr studio mit GCC.

so...bei drehendem motor hat man nun also ein "stehendes bild" von der gradscheibe. sagen wir mal die 0° markierung der skala ist im moment des "blitzens" unten. nun möchte ich aber, daß sich die markierung um beispielsweise 10° verschiebt. also muss die LED beim interruptaufruf nicht sofort angehen, sondern 1ms später.

hierzu wollte ich die funktionen _delay_ms() und _delay_us() verwenden.

#define F_CPU 16000000
#define <delay.h>

mit dem oszilloskop habe ich jedoch festgestellt, daß die pausen überhaupt nicht zu den von mir eingegebenen werten passen.

beispiele:

bei 1ms ist die pause ~2ms lang. bei 3...20ms passt es einigermaßen. bei 30...40ms ist kein unterschied zu 20ms zu erkennen.

bei 1...10µs beträgt die pause immer ~100µs.

das es für ms und µs einen maximalen wert, entsprechend der quarzfrequenz gibt ist mir bewusst.

für mein vorhaben wäre es schon von vorteil die zeiten/pausen genau einstellen zu können.

mache ich noch irgendetwas falsch...kann es sein, daß weniger als 100µs einfach nicht drin sind ?

alternativ könnte man einen timer benutzen...mit den funktionen wäre es allerdings praktikabeler.

vielleicht weiß ja jemand rat.

mfg

NACHTRAG:

kleine korrektur...es heißt natürlich

#define F_CPU 16000000
#include <delay.h>

und die maximums bei 16 mhz sind

16ms und 48µs

MasterFX
19.05.2006, 20:31
Richtig, darum ändern sich ab einem gewissen Wert die Delays auch nicht mehr. Warum 1ms so lang ist wird deutlich wenn du dir mal den Assembler Code anguckst. Es sind nämlich nicht nur die paar Befehle der Delay-Routine sondern da werden auch noch einige Register gespeichert (push) und dann kommt noch der eigentlich Jump zu der Routine dazu. Allerdings finde ich die eine ms mehr doch schon recht heftig. Eher würde ich erwarten, dass es sich bei den us stärker auswirkt.

simple
01.09.2006, 20:36
Ich habe das ähnliche Problem wie oben, dass _delay_us() und _delay_ms() absolut merkwürdige Werte liefern und dass sie zudem nicht mal linear fälschlich funktionieren.
Ob ich jetzt z.B. 100us, 300us oder 500us nehme macht fast keinen Unterschied.

Welche Möglichkeiten gibt es, Funktionen für exaktes Timing zu benutzen? Ich brauche relativ verlässliche Funktionen für den 1-wire-bus.

Ich bin für jeden Tip dankbar!

simple
04.09.2006, 09:38
So. Also bei mir war des Rästels Lösung:

a) um delays im µs Bereich zu erzeugen habe ich erstmal den CPU Takt von 1MHz auf 8MHz erhöht. Das macht denke ich auch Sinn, wenn man bedenkt, dass die _delay_us() Routine wohl viel mehr als 1-2 Anweisungen abarbeiten muss.

b) habe ich Compiler-Optimierungen verwendet. Damit kann ich mir jetzt perfekt getimte delays im niedrigen µs, z.B. 10µs