Programmierung des Mikrocontrollers mit C



Die umständliche Rechnerei kann man vermeiden, wenn man mit sogenannten logischen Verknüpfungen arbeitet, die da wären: UND, ODER, NICHT.


Beginnen wir mit der logischen Verknüpfung zweier binärer Variablen (A und B) durch ODER:


A
0
0 0 0
0
0
0
1

ODER

B:
0
0 0 0
1
0
0
0

ergibt:

X:
0
0 0 0
1
0
0
1

In A ist das 0. Bit gesetzt.
In B ist das 3. Bit gesetzt.
Im Ergebnis X ist sowohl das 0. Bit als auch das 3. Bit gesetzt.

Als Formel: X = A oder B

Und in der Programmiersprache C geht's mit: X = A | B ;

Das ist sehr praktisch und erspart uns viel Rechenarbeit!
Wieso?

In einem Register A soll das 0. Bit und das 4. Bit gesetzt werden, wobei die anderen Bits in A nicht verändert werden sollen.
Wir müssen nicht einmal wissen, was zur Zeit in A steht!
Wir könnten einfach folgendes programmieren:
A = A | 00010001 ;

Wäre prima, nur leider versteht unser avr-gcc diese Binärzahl nicht, so wie sie dasteht.
Man kann in der Programmiersprache C eine Binärzahl wie folgt schreiben, wobei das "0b" für "binär" steht:  0b00010001

Was auch funktioniert wäre:
A = A | 17 ;

Na toll! Wieder rechnen...

Aber ich habe verprochen, daß es auch ohne Rechnen geht.
Du kannst z. B. das 3. Bit im Port C wie folgt setzen:
PORTC = PORTC | _BV(PC3) ;

Merk Dir einfach: _BV steht für Binäre Variable (Das ist zwar gelogen aber läßt sich doch gut merken, oder?).

Wie kann man nun das 2. und 5. Bit im Port B setzen? Genau:
PORTB = PORTB | _BV(PB2) | _BV(PB5);

Prima, nicht?



Fahren wir fort mit NICHT:

gegeben ist A:

A:
0
0 0 0
0
1
0
1

NICHT A wäre dann:

X:
1
1 1 1
1
0
1
0

Alle in A gesetzten Bits sind im Ergebnis X nun gelöscht und umgekehrt.
In C programmiert: X = ~A ;
Wir werden das später benutzen, um Bits zu löschen.



Kommen wir zur logischen Verknüpfung zweier Variablen durch UND:


A:
0
0 0 0
0
1
0
1

UND

B:
0
0 0 0
1
1
0
0

ergibt:

X:
0
0 0 0
0
1
0
0

In X ist nur noch das 2. Bit gesetzt, weil es in A und in B gesetzt war.
In C programmiert: X = A & B ;
Auch dies werden wir später benutzen, um Bits zu löschen.



Kombinieren wir NICHT mit UND, ist es ganz einfach, einzelne Bits zu löschen.
Und das ohne zu rechnen und ohne zu wissen, was vorher in dem zu verändernden Register steht.

Bsp.: Es soll das 2. Bit im Port C gelöscht werden: PORTC = PORTC & ~_BV(PC2);
Wie das?
Leider ist die Erklärung dafür etwas unübersichtlich:


gegeben: PORTC

PORTC:    
0
0 0 1
1
1
1
1

Das 2. Bit im Port C:

_BV(PC2):  
0
0 0 0
0
1
0
0

NICHT _BV(PC2) ist dann:

~_BV(PC2):
1
1
1
1
1
0
1
1


somit:

PORTC:      
0
0 0 1
1
1
1
1
  

UND

~_BV(PC2):
1
1
1
1
1
0
1
1


ergibt:          
0
0
0
1
1
0
1
1

Wie Du siehst: das 2. Bit ist gelöscht und die anderen Bits sind unverändert.



Zusammenfassung:


Setzen des 0. Bits im PORT C:     PORTC = PORTC | _BV(PC0);
Löschen des 0. Bits im PORT C:   PORTC = PORTC & ~_BV(PC2);



Es geht noch kürzer!


Vielleicht erinnerst Du Dich: Man kann statt x = x + 3 auch schreiben: x += 3
Sieht zwar verwirrend aus, aber manche Programmierer sparen eben wo es nur geht.

Genau wie diese Addition geht es auch mit unseren Bitoperationen.

Setzen des 0. Bits im PORT C:
statt: PORTC = PORTC | _BV(PC0);  geht auch: PORTC |= _BV(PC0);


Löschen des 0. Bits im PORT C:
statt: PORTC = PORTC & ~_BV(PC0);  geht auch: PORTC &= ~_BV(PC0);



weiter