ich arbeite gerade die Arikel durch..1a die dinger..:) aber ich habe eine frage auf bestimmte code zeile: outp ((1 << RXEN) | (1 << TXEN), UCR); ich weiss was die zeile macht aber ich versteh die einzelnen zeichen net... ich kenne << nur als bit shiftoperand und nicht als zeichen um ein bit zu setzen. und dann noch der | das ist für mich eine veroderung und macht in meinen augen keinen sinn. wäre super wenn mir einer von euch helfen könnte.
Dient zum setzen der Bits RXEN (UART Receiver enable) und TXEN (UART Receiver enable) an der ensprechenden Position im UCR (UART Control Register).
> ich kenne << nur als bit shiftoperand So wird das hier auch gebraucht. > und dann noch der | das ist für mich eine veroderung auch das stimmt so. (1 << RXEN) schiebt die "1" um genau so viele Positionen nach links, wie der Wert in der Konstanten RXEN besagt. RXEN wurde die Zahl 4 zugewiesen, damit wird aus einer "1" durch 4x schieben das Bitmuster 00010000. (1 << TXEN) ergibt 00001000. Die bieden Klammern verODERt wird zu 00011000 und das wird dem Register UCR zugewiesen. Schmittchen.
das ist mir schon klar...ich hatte ja schon erwähnt das ich weiss was der befehl macht..nur ich weiss nicht wieso...
Ist doch ganz einfach zu lesen; sorgar die Klammerung sieht gut aus. Das ist schön kurz, knapp und präzise.
Ich könnte sowas natürlich auch mit 2 Hilfsvariablen und 5 Zeilen Code lösen, aber so viel Platz haben wir ja eigentlich gar nicht in unseren Controllern oder ;-) BYTE maske1, maske2; maske1 = 1 << RXEN; maske2 = 1 << TXEN; outp (maske1 | maske2, UCR); Das Verständnis der Bitschiebebefehle und der Bitoperatoren gehört zum Basiswissen bei der C-Programmierung. Kann bei Bedarf alles im Teil 1 des Tutorials nachgelesen werden. Gruss Christian
> aber so viel Platz haben wir ja eigentlich gar nicht in unseren Controllern oder
;-)
Ich sehe zwar den Smiley, trotzdem noch eine Ergänzung:
Die Schreibweise im 1.Posting belegt nur 1 Zeile im Editor, und nur eine
Zeile im Maschinencode (out UCR, 0x18). Die 0x18 kann der Compiler
(Präprozessor) schon erzeugen und muß nicht jedesmal zur Laufzeit
errechnet werden.
In Christians Beispiel werden im Normalfall 4 Zeilen Maschinencode
daraus. (2x Zuweisung, 1x OR, 1x OUT ; das shift löst der Compiler
selbst auf).
Theoretische Überlegung:
Eigentlich könnte der Compiler auch Chrisitans Code in eine einzige
Maschinencodezeile optimieren (out UCR, 0x18). Wenn zuvor sichergestellt
ist, dass kein Interrupt dazwischen kommen kann, dann kann ich mir keine
Programmkonstellation/zustand vorstellen, bei dem die Zeilen nicht durch
out UCR, 0x18 ersetzt werden können!? Ich vermute aber, daß das dem
Compiler bzw. den Compilerprogrammierern zu weit geht und es nicht so
gemacht wird.
Schmittchen.
@Schmittchen Wenn Du Variablen verwendest, denkt der Compiler, daß Du Dir dabei was gedacht hast und optimiert sie nicht so einfach weg. Sonst hättest Du ja #define genommen: #define maske1 (1 << RXEN) #define maske2 (1 << TXEN) outp (maske1 | maske2, UCR); So sinds dann wieder nur 2 Zeilen Assembler. Peter
> Wenn Du Variablen verwendest, denkt der Compiler, daß Du Dir dabei was gedacht
hast
Ja klar, aber in dem speziellen Falle könnte er sie wegoptimieren,
ohne die Funktion des Programmes zu verändern. (Ich geb ja zu, daß das
ein sehr spezieller, konstruierter und weithergeholter Fall ist -
genauso wie zu fordern, daß der Compiler aus deinem Code nur 1 Zeile
machen soll.).
Schmittchen.
@Schmittchen "genauso wie zu fordern, daß der Compiler aus deinem Code nur 1 Zeile machen soll" Ist doch unmöglich ! Um einen Wert in ein I/O-Register zu schreiben, brauchst Du mindestens 2 Instruktionen: ldi r16, 1<<RXEN^1<<TXEN out UCR, r16 Direkt irgendwas im I/O zu machen geht nur beim 8051 (MOV, INC, DEC, DJNZ, ANL, ORL, XRL). Deshalb ist ja Code auf dem 8051 typischer Weise kleiner als auf dem AVR. Peter
> Um einen Wert in ein I/O-Register zu schreiben, brauchst Du mindestens 2 Instruktionen: Stimmt! Für mich war das eine Instruktion, aber das kann der AVR ja leider nicht. Also stimmen meine Angaben oben auch nicht ganz. Aber manchmal geht der Compiler ja auch zu weit... siehe Beispiele leere Warteschleife wegoptimieren (kann der Compiler ja nicht wissen) oder die volatile-Geschichte. In beiden Fällen muß man den Compiler explizit darauf "hinweisen". Schmittchen.
> Aber manchmal geht der Compiler ja auch zu weit... siehe Beispiele leere
Warteschleife wegoptimieren ...
Nee, das ist schon richtig, das unnützer Code wegoptimiert wird. Wenn
das nicht gemacht würde, müsste man auch die Kommentare übernehen und
nicht wegoptimieren!
Wenn Optimierung eingeschaltet ist, sollte eine leere Warteschleife
immer wegoptimiert werden.
Eine Warteschleife sollte niemals wegoptimiert werden, wenn der Compilerbauer mitgedacht hat. Optimieren heißt doch nur sinnlosen Code zu entfernen aber eine Warteschleife ist doch eindeutig als sinnvoll zum Warten zu erkennen. Wenn ein Compilerbauer also leere Schleifen wegoptimiert, hat er entweder keine praktische Programmiererfahrung oder er will den Nutzer ärgern. @Jonas, stimmt, die meisten 8051 laufen mit 1 MIPS (Quarz = 12MHz), weil das oftmals mehr als ausreichend ist. Aber für die Geschwindigkeitsfetischisten gibts auch 8051-er mit max 50 MIPS (bzw. 100 MIPS als Samples), z.B von Cygnal. Peter
Diese Aussage kann ich so nicht stehen lassen. Bedenkt bitte, dass der C-Compiler nicht ausschliesslich zum Programmieren von Mikrocontrollern entwickelt wurde und bei "normalen" Anwendungen soll schliesslich nicht gewartet, sondern möglichst zügig gearbeitet werden. Insofern ist es aus Sicht des Compilers völlig in Ordnung, für ihn sinnlose (weil leere) Loops wegzuoptimieren. Christian
>Eine Warteschleife sollte niemals wegoptimiert >werden, wenn der Compilerbauer mitgedacht hat. Ja, aber eine leere Schleife ist doch keine Warteschleife, ausser man sagt das dem Compiler explizit. Ansonsten könnte der Compiler ja nichts optimieren! Beim MSPGCC sieht eine ganz einfache Warteschleife deshalb so aus: for(i=0;i<1234;i++) _asm_ __volatile__("; loop"); Das die Schleife ohne volatile wegoptimiert ist doch auch das was man haben möchte, denn nach einigen tausend Zeilen Code kann ein Mensch wegoptimierbaren Code kaum erkennen, so das der Compiler das übernehmen muss.
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.