Forum: Mikrocontroller und Digitale Elektronik C-Code verstehen


von anfänger (Gast)


Lesenswert?

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??

von Christian R. (supachris)


Lesenswert?

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....)

von Karl H. (kbuchegg)


Lesenswert?

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.

von crazy horse (Gast)


Lesenswert?

> 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)....

von anfänger (Gast)


Lesenswert?

Warum nimmt man denn nicht eine "fertige Maske", z.B.

while(EECR & 0x02);

von F. K. (freddy436)


Lesenswert?

Es erhöht die Lesbarkeit extrem, die Portierung auf andere µCs wird 
dadurch ebenfalls deutlich einfacher.

von Christian R. (supachris)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

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


Lesenswert?

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. ;-)

von C Hasser (Gast)


Lesenswert?

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.

von Tcf K. (tcfkat)


Lesenswert?

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
Noch kein Account? Hier anmelden.