hi, kann mir jemand sagen wie viele takte EIN Durchlauf einer simplen for-Schleife hat bzw. wie ich das rausfinden kann?( z.B: for(i=1;i<100;i++); ) und wie ist das mit einer while schleife?z.B.x=100; while(x--); Und noch eine frage am rande kann man eine if-bedingung in eine for-schleife einbauen? z.B. for(i=1;i<100;if(x==3)i++;); Hoffe ihr könnt mir helfen Gruss Chrigu
Die erste Frage lässt sich nur durch Ansehen des vom Compiler erzeugten Assemblerlistings klären. Welche Compileroption für die Erzeugung eines kommentierten Assemblerlistings (C-Quelltextzeilen als Kommentare eingefügt) zuständig ist, wirst Du der Dokumentation entnehmen können. Das wurde hier aber auch schon gelegentlich besprochen. Was spricht dagegen, das in der zweiten Frage formulierte Konstrukt einfach auszuprobieren? Wenns nicht geht, wird das der Compiler schon sagen.
hi, danke:D auf die idee mit dem compilieren hätt ich au ckommen können, danke!! Aber nun habe ich in einer vom compiler erzeugten *.lss Datei gefunden: .... int x, y=3; for(x=100;x;)if(y==3)x--;; 64: 84 e6 ldi r24, 0x64 ; 100 66: 90 e0 ldi r25, 0x00 ; 0 68: c2 97 sbiw r24, 0x32 ; 50 6a: f1 f7 brne .-4 ; 0x68 6c: 00 c0 rjmp .+0 ; 0x6e .... ist das jetzt der asm-codefür dieses Konstrukt? also dauert dies 5 takte? habe leider null ahnung von asm... Danke schonmal ;-)
Ich denke, das was du da probierst wird nicht ganz funktionieren. Die Eingangsbedingungen in die for-schleife sind vorbestimmt. Ein Optimierer kann diese Schleife voll auflösen da er sämtliche parameter kennt. Oder deutlicher gesagt die ganze Schleife kann vollständig eliminiert werden. Solltest du eine delay Routine programmieren wollen, so füge ein nop ein. Du willst warten bis y 100mal 3 war. y ändert sich nebenher z.B. aus einem Interrupt. Ohne das kleine Wörtchen volatile wird das nicht funktionieren.
Das ist tatsächlich der Assembler-Code für die for-Schleife. Aber wie Wolfram schon sagte: Deine Schleife macht anscheinend nicht viel Sinn... Da y nicht als volatile deklariert ist, wird die if-Abfrage komplett wegoptimiert. Außerdem macht der Compiler aus der eigentlichen for-Schleife mit (gewollten) 100 Durchläufen eine mit 2 Durchläufen (x wird nicht um 1 sondern um 50 dekrementiert). Compilier das ruhig mal mit ausgeschalteter Optimierung und schau Dir das Ergebnis an. Da kommt wesentlich mehr Code raus... Ganz allgemein: Wenn Du anhand der .lss-Datei die Ausführungszeiten ermitteln willst, musst Du Dir das Instruction Set Manual mal vornehmen. Da steht für jeden einzelnen Befehl drin, wie viele Taktzyklen er braucht. Es gibt nämlich auch Befehle, die mehr als einen Zyklus brauchen (z.B. sbiw braucht zwei) und es gibt Sprung- und Verzweigungs-Befehle, die je nachdem, ob die Bedingung wahr oder falsch ist, unterschiedliche Ausführungszeiten haben (z.B. brne).
> Solltest du eine delay Routine programmieren wollen, so füge > ein nop ein. Oder nimm gleich die Funktionen aus <util/delay.h>, dort haben sich andere Leute schon die Mühe gemacht, die Zyklenzahlen auszuzählen.
Vor allem haben die auch inline-Assembler verwendet, so daß die Zyklenzahlen nicht von den Optimierungseinstellungen oder der Version des Compilers abhängen.
Ganz anderer Ansatz: Mit einem Frequenzzähler am laufenden System ausmessen. Das ist manchmal einfacher als komplexe Assembleropcodes nachzuschlagen. int main(void) { while(1) { port_einschalten(); /* Messobjekt z.B. */ delay_funktion(1000); port_ausschalten(); } } Die Ausführungszeit ist 1/Frequenz. Die Messung wird um so genauer, je "enger" sich die Schaltbefehle am Untersuchungsobjekt befinden. Also ggf. statt Funktionen Makros benutzen. Noch ein anderer Ansatz: Manche Debugger/Simulatoren zeigen die benötigte Zyklenzahl für ein Stück Assemblercode auch an.
while(1) { port_einschalten(); delay_funktion(1000); port_ausschalten(); delay_funktion(1000); } Sonst ist die Pulsweite ein wenig klein :)
Stimmt. Danke! Typischer Fall von ins Forum tippen und nicht nachdenken. Beim letzten Mal hatte ich es nämlich so gemacht while(1) { port_toggle(); /* Messobjekt z.B. */ delay_funktion(1000); }
Hey, danke viel mal! Ich habe die optimierung mal ausgeschaltet und tatsächlich kam ordentlich viel mehr code raus. Damit das ganze nicht so wegoptimiert wird muss ich also die variablen als volatile deklarierten. Allerdings ist mir folgendes nicht ganz klar: > Solltest du eine delay Routine programmieren wollen, so füge > ein nop ein. Wo soll ich nop einfügen?? einfach in die Schleife? for(blabla) {bla; nop} ??? Grüsse Chrigu
Ich verstehe nicht, warum sich Leute immer das Leben unnötig schwer machen müssen und vielleicht noch umständlich irgendwelche Delays ausmessen müssen. Und beim nächsten Quarz oder der nächsten Compilerversion stimmt dann gar nichts mehr und der Ärger geht von vorne los. Man kann doch prima einen Timer nehmen und Compiler unabhängig beliebige Delays für beliebige Quarze bequem vom Präprozessor berechnen lassen: http://www.mikrocontroller.net/forum/read-4-84831.html#new Peter
Peter, dort wo du schon warst, müssen andere (ich) erst noch hinkommen ;-) Für einen Anfänger (wie mich) ist das Ausmessen der am schnellsten erfolgversprechende Weg. Und der Appetit kommt bekanntlich beim Essen... Zum Glück gibt es dann feine Kochrezepte wie deine "genaue Sekunde"!
den Timer könnte ich schon nehmen, habe den timer 0 und 1(mega8) allerdings schon belegt, möchte nicht noch den letzten auch nehmen (mühsam):-). Vielleicht nehme ich den am ende doch, aber wo muss ich grundsätzlich nop hinschreiben? kann ja auch sonst mal nützlich sein denke ich. Danke:) (PS: ich brauche eigentlich nicht direkt ein delay, würde auf umwegen aber auch damit gehen.)
Man nimmt im Wesentlichen einen Timer, der den "Systemtakt" liefert, und lässt den dann alle zeitgesteuerten Ereignisse abarbeiten. Damit braucht man nicht für jede Verzögerun einen neuen Hardware-Timer. Der NOP gehört in die Schleife: _asm_ volatile("nop"); damit diese nicht wegoptimiert werden kann. Aber s. o., wenn schon Verzögerung mit Schleifen, nimm besser das, was andere dir schon vorgearbeitet haben. Für kurze Verzögerungen (also vor allem solche im Mikrosekundenbereich) sind delays oft genug vonnöten, weil sich das Anwerfen eines Timers dann nicht erst lohnt.
> Für einen Anfänger (wie mich) ist das Ausmessen der am schnellsten > erfolgversprechende Weg. Für einen Anfänger ist der erfolgversprechendste Weg Funktionen zu benutzen, die andere bereits vorgefertigt haben und die daher auch funktionieren. In 'delay.h' gibt es eine fix fertige funktionierende Verzögerungsschleife, wenns denn unbedingt eine Verzögerung sein soll.
>Für einen Anfänger ist der erfolgversprechendste Weg Funktionen >zu benutzen, die andere bereits vorgefertigt haben und die >daher auch funktionieren aber nur wenn er deren Funktionsweise verstanden hat. gilt insbesondere für die empfohlenen delayroutinen Lies bitte die Dokumentation und Einschränkungen genau durch.
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.