hallo ich verstehe folgenen C-Coden nicht while(EECR & (1<<EEWE)); es geht darum das bit EEWE im register EECR zu prüfen, aber wie funktioneiert das mit dem schiebebefehl und dem UND operator? kann man das bit nicht direkt abfragen??
In der Schleife wird die um ein paar Stellen nach links verschobene 1 solange mit dem EECR Register UND verknüpft, bis das Ergebnis Null ist. Also das Bit nicht mehr gesetzt. Im Prinzip wird das Register bis auf das EEWE Bit gelöscht und bei dieser Aktion gleich geschaut, ob es dann 0 oder eben was anderes ist. Bits kann man nicht direkt abfragen. Ein µC kann im innersten Kern nix andres als addieren, Bits schieben, und dann immer Flags setzen (Zero, Carry....)
anfänger wrote: > hallo > > ich verstehe folgenen C-Coden nicht > > while(EECR & (1<<EEWE)); > > > es geht darum das bit EEWE im register EECR zu prüfen, aber wie > funktioneiert das mit dem schiebebefehl und dem UND operator? > kann man das bit nicht direkt abfragen?? EEWE ist eine Zahl, die angibt, das wievielte Bit (rechts wird mit 0 zu zählen angefangen) im Register gemeint ist. Nehmen wir mal an, EEWE hätte den Wert 3. Wenn du nun eine 1 nimmst Binär 00000001 und diese 1 genau 3 mal nach links schiebst Binär 00001000 dann erhältst du eine Binärzahl, die genau an der Bitposition 3 (von rechts beginnen zu zählen, mit 0 beginnen zu zählen) eine 1 aufweist. Das ist die Maske die für die UND Verknüpfung benutzt wird. Das &, als binäre Operation wirkt bitweise auf seine beiden Operanden. Dh. in EECR & 00001000 wird jedes einzelne Bit von EECR mit dem jeweils korrespondierendem Bit in der Maske 00001000 UND verknüpft. Die Logiktabelle für UND sieht so aus A B A und B 0 0 0 1 0 0 0 1 0 1 1 1 Was auffällt: Wenn B 0 ist, dann ist der Ergebnis auf jeden Fall 0. Wenn B aber 1 ist, dann ist das Ergebnis identisch zu A. Angewendet auf die Maske 00001000 bedeutet das, das alle Bits bei denen in der Maske eine 0 steht im Ergebnis auf jeden Fall 0 sind. Nur dort wo in der Maske eine 1 steht, ist das Ergebnisbit identisch mit dem Bit vom anderen Partner der UND Operation. In Summe EECR & 00001000 setzt im Ergebnis also alle Bits bis auf Bit 3 definiert auf 0. Ob Bit 3 des Ergebnisses 0 oder 1 ist, hängt davon ab, ob das Bit 3 in EECR 0 oder 1 ist. > kann man das bit nicht direkt abfragen?? Das ist die C-Schreibweise für eine Bit Abfrage. Der Compiler erkennt dieses und ersetzt den kompliziert anmutenden Ausdruck durch die entsprechenden Bit Befehle in Assembler, so es möglich ist. Aber in C ist die kleinste Einheit nun mal ein konmplettes Byte.
> Bits kann man nicht direkt abfragen.
nana, so kann man das nicht stehen lassen.
Man kann Bits schon direkt abfragen - das Problem ist, dass C keine
Bit-Datentyp kennt. Deshalb dieses Konstrukt. Jeder halbwegs brauchbare
Compiler wird dieses auf einen Einzelbit-Befehl (sbic/sbis)
zurückführen.
Einige Compiler können dies dennoch, ist dann aber nicht mehr ANSI-C.
CodeVision:
if (EECR.EEWE)....
Es erhöht die Lesbarkeit extrem, die Portierung auf andere µCs wird dadurch ebenfalls deutlich einfacher.
Naja, Lesbarkeit....dies (1<<EEW) Konstrukt is auch nich auf den Ersten Blick erkennbar. Beim mspgcc ist in den Headern immer gleich die 0x20 oder 0x1000 oder was auch immer in den defines, da kann man dann einfacher (und meiner Meinung nach verständlicher) schreiben: while(EECR & EEW); Die Aussage, dass man Bits nicht direkt abfragen kann, bezog sich auf Ansi-C.
und um das klar herauszustreichen: 1 << EEWE ist genauso eine 'fertige Maske' wie 0x02. Soll heissen, das beides zum exakt gleichen Code führt. Nur, wie F. Kriewitz bereits sagte, wenn beim nächsten µC aus der selben Prozessorfamilie, EEWE plötzlich nicht mehr an Bitposition 2 anstelle von 1 liegt, dann brauchst du bei 1 << EEWE gar nichts tun, der Compiler erledigt das Aufsetzen der neuen Maske. Während bei einer direkten Angabe von 0x02 der Programmierer dafür verantwortlich ist, dass die 0x02 gegen 0x04 ausgetauscht wird. Du ahnst schon worauf das hinausläuft: Im Zweifelsfall lasse ich den Compiler die Arbeit machen, denn der vergisst nichts :-)
anfänger wrote: > Warum nimmt man denn nicht eine "fertige Maske", z.B. > > while(EECR & 0x02); Man hätte EEWE natürlich als Maske definieren können, so hätte das wohl jeder C-Programmierer geschrieben: ... #define EEWE 0x02 ... while (EECR & EEWE) /* wait */; Aber: all diese Namen sind nicht von C-Programmierern erfunden worden, sondern von Atmel selbst, und sie sollen auch den Assemblerprogrammierern von Nutzen sein. Da der AVR nun auch noch CPU-Befehle hat, in denen nicht mit einer Bitmaske sondern mit einer Bitnummer gearbeitet wird, sind sämtliche IO-Bits als Bitnummern deklariert. Für C muss man sie daher in eine Maske umwandeln, indem man (fiktiv, nur für die Compilierung) eine 1 um die entsprechende Bitnummer nach links schiebt. Wie Karl Heinz schon anmerkt, ersetzt der Optimierer das letztlich durch die Maske -- oder aber (im Falle des AVR) durch die Bitnummer im entsprechenden SBI/CBI/SBIR/CBIR-Befehl. Letztere muss sich der Optimierer aber aus der Bitmaske zurück berechnen. ;-)
Mangels eines Datentypen wird ein schwer lesbares Konstrukt in eine unpassende Anweisung uebersetzt. Falls der Optimierer nun klug genug ist, ersetzt er dieses Bytecommands durch ein Bitcommand. Seltsamerweise haben fast alle Controller Singlebit Befehle, und C fand in den vergangenen 20 Jahre noch nicht zum Singlebit Datentypen. Man koennte fast meinen C passt nicht zu Controllern und will es auch nicht. ==> in den Kuebel damit. Das Leben ist zu kurz und zu muehsam um sich mit C zu plagen.
Na ja, die C-Hasser können sich ja in BASIC, Pascal, FORTRAN, COBOL, Modula, ADA, Smalltalk, Lisp, Forth, Python oder Java austoben... so kommt man sich auch nicht ins Gehege... ;) Viel Spaß damit!
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.