Forum: Compiler & IDEs Wegen Delay Funktion _delay_us(double __us)


von Mister mit Kanister (Gast)


Lesenswert?

Hi,

ich hab eine Frage zur o.g. Funktion von der delay.h:

Es heißt: "The maximal possible delay is 768 µs / F_CPU in MHz."

Bei mir @16Mhz kann ich also max. 48µs Delay machen.

Anwendungsspezifisch will ich aber auf bis ca. 20000µs also 20ms delay 
machen können und das mit der Genauigkeit von +/- ein paar µs.

Jetzt woll ich mich umhöreh ob es eine bessere Funktion gibt, weil die 
Funktion in der delay.h kann ich nicht erweitern.

Also höchstens die Funktion x mal dann für z.b. 4800µs dann 100x 
aufrufeun?

Geht das nicht irgendwie einfacher?

von johnny.m (Gast)


Lesenswert?

> Jetzt woll ich mich umhöreh ob es eine bessere Funktion gibt,...
Ja, nen Timer. Mit delay-Funktionen arbeitet man eigentlich 
grundsätzlich nur dann, wenn man kurze Verzögerungszeiten benötigt, für 
die es sich nicht lohnt, einen Timer anzuwerfen (vorausgesetzt, Du hast 
einen Timer für diese Aufgabe frei). Und wenns bei dem gewünschten 
Bereich auf einige µs genau sein soll, wirst Du um einen Timer eh nicht 
rumkommen, außer Du programmierst Dir in Assembler selber eine Routine, 
die in der Lage ist, die gewünschte Funktion zu erfüllen (CPU-Takte 
zählen). Bei Mehrfachaufrufen der delay-Funktionen müsstest Du genau 
kontrollieren, was der Compiler aus der Schleife, in der Du die Aufrufe 
machst, macht. Das führt sonst zu weiteren Ungenauigkeiten.

von Stefan (Gast)


Lesenswert?


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Beachte auch, dass diese _delay_XX-Funktionen ausschließlich mit
zur Compilezeit bekannten festen Werten benutzt werden dürfen.
Alles andere verursacht mehr Laufzeit-Overhead, als du dir mit deinen
+/- paar Mikrosekunden aufhalsen möchtest.

von johnny.m (Gast)


Lesenswert?

Stefan hat natürlich recht. _delay_ms bekommt ja einen double übergeben 
(oh, wie konnte ich das vergessen... wird Zeit, Feierabend zu machen). 
Da kannste natürlich z.B. mit _delay_ms(10.001) eine sehr gute 
Genauigkeit erreichen. Allerdings geht _delay_ms bei 16 MHz auch nur bis 
ungefähr 16 ms...

von johnny.m (Gast)


Lesenswert?

...Upps zu schnell abgeschickt... Das was Jörg sagt, ist natürlich auch 
zu beachten. Wenn Deine Werte erst zur Laufzeit des Controller-Programms 
bekannt sind, wirst Du um einen Timer wohl tatsächlich nicht rumkommen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Alternative, falls Timer aus irgendwelchen Gründen nicht geht, aber
nur ein paar feste Werte gebraucht werden: die Zyklenzähler in einer
lookup table vorberechnen und dann _delay_loop_2 und ggf. danach
noch _delay_loop_1 damit aufrufen.

Manchmal wäre es natürlich hülfreich, wenn die Leute ihr eigentliches
Problem posten würden...

von Mister mit Kanister (Gast)


Lesenswert?

Danke Leute! Eure Hilfe ist super!

Das mit dem double Übergabe in der _delay_ms... habe ich schlichtweg 
übersehen, damit sollte es dann eigentlich funktionieren. Sonst muss ich 
mal die Timer neu programmieren.

Die Ursache meines Problems kommt daher, dass ich mit Ultraschall 
experimentiere und zu genau definierten Zeiten ein Schallimpuls 
rausschicken will. Um dabei auf eine Genauigkeit von 1mm Auflösung im 
Messbereich zu kommen brauch ich schon eine Genauigkeit im µs-Bereich 
(Schalllaufzeit 1mm ca. 3µs).

D.h. so wie ich das sehe und meinem Compiler alle Parameter bekannt 
sind, sollte es dann keine Probleme mit der Genauigkeit geben!?

Ich werd das jetzt mal ausprobieren mit der ms-Funktion.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, wenn alles zur Compile-Zeit bekannt ist, sollte es kein Problem
sein.

Ich würde den Timer jedoch für die sinnvollere Wahl halten.  Wie
generierst du den Ultraschall selbst, mit dem AVR oder mit einer
externen Schaltung?  Wenn es ein externer Generator ist, kannst du
denn ja mittels des OCx-Ausgangs automatisch vom Timer aktivieren
lassen, also keinerlei Software-Latenz.

von Mister mit Kanister (Gast)


Lesenswert?

Hi Jörg,

der Schall wird extern generiert. Lediglich mit dem µC gebe ich ein 
Enable/Disable Signal an die Sende-/Empfangsstufe. Die Sendestufe 
besteht aus einem NE555 Oszillator, der auf die Resonanz des 
Piezoschwingers abgestimmt ist. Nachfolgend kommt dann eine 
Trafoschaltung, die mir die 5V TTL Wechselspannung auf ca. 300V 
hochtransformiert.

Das Enable Signal hab ich bisher noch am normalen Port hängen, aber Dein 
beschriebener OCx-Ausgang wär dann mit Verwendung eines Timers die 1. 
Wahl.

Theoretisch könnte ich mit dem OCx eine Wechselspannung erzeugen und 
dann direkt auf die Sendestufe gehen, dann könnte ich mir den 555 
sparen.

Ich hab mal ein Test gemacht. Funktioniert gut bis zum Delay von 16ms, 
mehr packt er halt nicht. Fürs erste reicht das mal, für längere 
Pausenzeiten mach ich das dann mit nem Timer.

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.