hallo, ich glaube ein problem mit volatile in verbindung mit delay loops (z.b. _delay_us()) im avr gcc gefunden zu haben. der angehaengte code tut nicht das, was er meiner meinung nach tun sollte - das delay stimmt einfach nicht immer. mit der mit 'nicht ok' markierten zeile funktionierts nie, mit der 'ok' markierten zeile funktionierts, wenn ich die optimierung auf s schalte - ohne optimierung funktionierts nie... nicht funktionieren heisst: an nen logic-analyzer angeschlossen sieht man, dass das delay scheinbar beliebig (auf jeden fall viel zu lang) ist...unabhaengig vom wert von val. verwende das aktuelle WinAVR von avrfreaks... ach ja, volatile, weil auch aus einer interrupt-routine darauf zugegriffen wird - ich hab den code nur der uebersichtlichkeit halber aufs notwendige reduziert. kann das ein compiler-bug sein oder versteh ich irgendwas nicht?
Ohne jetzt in die Doku zu schauen - bist Du Dir sicher, dass delay_us ein double erwartet? Stefan
Diese beiden Threads hast Du gesehen? -> http://www.mikrocontroller.net/forum/read-2-163391.html -> http://www.mikrocontroller.net/forum/read-2-162211.html
Tatsächlich: double ... nehme alles zurück ... Stefan
Gleitkommaargumente sind nur im konstanten Kontext zugelassen, bei dem der Compiler das wegoptimieren kann. Ansonsten müssen die Argumente in der Tat uint16_t sein, weil das der Datentyp ist, den die fertige Schleife selbst nehmen will. Nee, Moment mal, _delay_us benutzt ja _delay_loop_1, da ist es sogar uint8_t (bzw. wird auf den reduziert). Sorry, das müsste man wohl in der Doku noch ein wenig hervorheben, ist mir bislang auch noch nicht untergekommen. Kannst ja gern einen Bugreport dafür schreiben. Der wesentliche Sinn dieser inline-Funktionen ist die Realisierung kurzer fester Verzögerungen, nicht ihr universeller Einsatz an Stellen, wo ein Timer deutlich angebrachter wäre. Übrigens: __us hat in einem Anwenderprogramm nichts verloren. Schreibe bitte us, microseconds, micro_seconds, u_s oder was auch immer -- aber nichts, was mit einem Unterstrich anfängt. Du kommst sonst über kurz oder lang in Teufels Küche.
Selbst für mehrere kurze Verzögerungen würde ich das übrigens nicht so machen. Du hättest dann zur Laufzeit Multiplikationen und/oder Divisionen. Der Sinn der _delay_us und _delay_ms Funktionen ist, dass der Compiler diese (teuren) Operationen zur Compilezeit auflösen kann. Besser vielleicht eine switch-Anweisung, die mehrere delay-Werte vorgibt oder die delay-Werte in einem Array hinterlegen.
@OldBug die helfen mir leider nicht weiter... @Jörg das mit den __ ist von cut&paste uebriggeblieben... auch wenn ich alle doubles zu uint8_t s mache passiert dasselbe...irgendwas stimmt einfach nicht - ich muss doch auch die variable als parameter uebergeben koennen ohne das dann nix mehr richtig geht??? ach ja, wenn ichs mit der 'ok' zeile kompiliere ist das file ca. 200 gross - mit der 'nicht ok' zeile ca. 900... auch wenn man prinzipiell den timer nehmen sollte, so sollte das aber doch auch funktionieren oder? ein array wuerde mir nichts bringen, weil die werte wirklich immer unterschiedlich sind.
> das mit den __ ist von cut&paste uebriggeblieben... Dann ist der Code, von dem du kopiert hast, der Übeltäter und sollte verbessert werden. Führende Unterstriche sind wirklich böse in C und C++, gewöhn dir das am besten gar nicht erst an. Hinten angehängte Unterstriche kann man eh besser lesen. ;-) > ach ja, wenn ichs mit der 'ok' zeile kompiliere ist das > file ca. 200 gross - mit der 'nicht ok' zeile ca. 900... Kein Wunder, bei letzterem muss das Programm Gleitkommaarithmetik betreiben und braucht dafür natürlich viel mehr Code. > auch wenn ich alle doubles zu uint8_t s mache passiert > dasselbe...irgendwas stimmt einfach nicht - ich muss > doch auch die variable als parameter uebergeben koennen > ohne das dann nix mehr richtig geht??? Hm, vielleicht verlangt delay_us wirklich Compile-Time-Konstanten als Parameter, da ansonsten Divisionen und/oder Multiplikationen zur Laufzeit ausgeführt werden müssten. </IMHO>
> Hm, vielleicht verlangt delay_us wirklich Compile-Time-Konstanten > als Parameter, da ansonsten Divisionen und/oder Multiplikationen zur > Laufzeit ausgeführt werden müssten. Habe eben nochmal nachgesehen: genau so ist es. Damit vervielfacht sich natürlich die Verzögerung heftig. In dem Falle muss man dann doch wieder selbst auf die low-level Funktionen _delay_loop_1 und _delay_loop_2 zurückgreifen und die Berechnung der Zeitkonstanten selbst vornehmen. Allerdings würde ich auch hier jede Art von Division zur Laufzeit vermeiden, auch im Integer-Bereich ist die für den Anwendungsfall immer noch viel zu teuer.
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.