Dieser Teil meiner Homepage soll helfen, die Grundlagen und die unter einem extra Link verfügbaren Programme zu verstehen. Schließlich ist nicht jeder ein gelernter C-Programmierer ;-)
Es sei noch erwähnt, dass es sich hierbei hauptsächlich um Bitoperatoren handelt, welche allerdings von Compiler zu Compiler verschieden sein können. Ich arbeite mit avr-gcc.

Definieren eines Ports als Eingang:
DDRx = 0x00;                //Hierbei steht x für den jeweiligen Port
z.B. DDRD = 0x00;        //das Kürzel 0x steht für die hexadezimale Schreibweise

Aktivieren bzw. Deaktivieren der internen Pull-Up Widerstände:
PORTx = 0x00;                //Deaktivierung
PORTx = 0xff;                  //Aktivierung
z.B. PORTD = 0x00;

Definieren eines Ports als Ausgang:
DDRx = 0xff;
z.B. DDRB = 0xff;

Veränderung der Pegel am Ausgang:
PORTB = 0x00;            //Low-Pegel, es können beliebige 8 Bit Werte in das Register geschrieben werden
PORTB = 0xff;              //High-Pegel

Speichern des Status an einem Eingangsport in einer Variablen (z.B. temp):
unsigned char temp = PIND;

Schreiben eines Wertes in ein beliebiges Register des Controllers:
TCCR0 = 0x4F;            //alternativ auch TCCR0 = 79

Gezieltes Setzen eines Bits in einem Register:
PORTB |= (1<<PB2)    //Setze Bit in PB2 an PORTB
alternativ: PORTB |= (1<<2)
Erklärung: Der senkrechte Strich | bedeutet ein logisches bitweises ODER. Man hätte auch schreiben können PORTB = PORTB | 0x04. Die 0x04 ergibt sich, wenn man eine '1' in Bit 0 schreibt und dann zweimal nach links schiebt. Wie sicherlich bekannt ist, liefert ein ODER eine '1', wenn beide zu vergleichenden Bits oder auch nur eines logisch '1' sind. Somit wird durch den Befehl in PB2 das Bit gesetzt, falls es nicht bereits gesetzt ist.

Gezieltes Löschen eines Bits in einem Register:
ADCSRA &=  ~(1<<ADEN)    //Lösche Bit in ADEN in ADCSRA-Register
Erklärung: Das kaufmännische UND & bedeutet ein logisches bitweises UND. Man hätte auch schreiben können ADCSRA = ADCSRA & ~(1<<ADEN). Wie sicherlich bekannt ist, liefert ein UND eine '1', wenn beide zu vergleichenden Bits logisch '1' sind. Das Tilde-Zeichen steht für eine bitweise Negation von ADEN. Genauer: Steht in ADEN eine '1', so wird diese durch '~' zu '0'. Nun wird die vorherige '1' mit der '0' UND-verknüpft, was logischerweise '0' liefert. Das Bit wird gelöscht.
Wem das alles zu umständlich ist, der kann sich auch einfach folgende Makros definieren:
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
Die Verwendung erfolgt dann folgendermaßen:
SETBIT (PORTD, PD2);
bzw.
CLEARBIT (PORTD, PD2);

Setzen mehrer Bits in einem Register:
DDRD |= 0x0C    //Setze Bit 2 und 3 in DDRD (0x0C = 0b00001100)
alternativ: DDRD = (1<<2) | (1<<3);

Löschen mehrerer Bits in einem Register:
ADCSRA &= ~(0x0C)    //Lösche Bit 2 und 3 in ADCSRA
alternativ: ADCSRA = ~(1<<2) & ~(1<<3);
Natürlich kann man die Bits auch mit ihren eigentlichen Bezeichnungen ansprechen, so sie denn welche haben (siehe Headerfile des MC):
ADCSRA = ~(1<<ADPS2) & ~(1<<ADIE);


Prüfen ob Bit gesetzt ist:
if (USR & (1<<TXC))    //Kontrolliere, ob TXC-Bit in USR gesetzt ist
Auch hierfür lässt sich ein Makro definieren:
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
Die Verwendung erfolgt dann so:
if (CHECKBIT (USR, TXC)) {
    //mache irgendwas
}

Prüfen ob Bit gelöscht ist:
if (!(SPSR & (1<<WCOL)))    //solange WCOL-Bit in SPSR nicht gesetzt ist ...
Mit dem oben definierten Makro könnte man auch schreiben:
if (!(CHECKBIT (SPSR, WCOL))) {
    //mache etwas
}

Prüfen von Registerinhalten:
if (UDR & (0xF3))    //wenn UDR-Register UND 0xF3 nicht 0 sind ...
if (!(UDR & (0xF3)))    //wenn UDR-Register UND 0xF3  0 sind ...

Verschieben von Bits:
nach links:        PORTB = (temp<<4);        //Verschiebung um 4 Stellen nach links
nach rechts:      PORTB = (temp>>4);        //Verschiebung um 4 Stellen nach rechts
PORTB = temp>>8;    //falls temp eine 16 Bit Variable ist, nutzt nur die oberen 8 Bit

Maskierung von Bits:
TCNT1 = temp&0x00FF;    //nutzt nur die unteren 8 Bit (Bitmaske)

Partielles Schreiben in einen Port:
PORTD = (PORTD & 0x0f) | (temp << 4);    //nur das High-Nibble (Bit 4...7) wird verändert
Erklärung: PORTD & 0x0f löscht zuerst das gesamte High-Nibble und erhält lediglich das Low-Nibble in seinem Anfangszustand. (temp << 4) bewirkt, dass das Low-Nibble von temp in dessen High-Nibble geschoben wird. Das Low-Nibble wird vom MC mit 0000 aufgefüllt. Nun erfolgt noch ein bitweiser ODER-Vergleich von temp und PORTD. Da das Low-Nibble von temp '0' ist, wird das Low-Nibble von PORTD durch den ODER-Vergleich nicht verändert. Lediglich das High-Nibble wird durch das High-Nibble von temp aktualisiert.

Das Exklusiv-ODER:
PORTB ^= 0xff;
Ein EXOR liefert '1', wenn sich beide Variablen unterscheiden. Sind beide '1' bzw. '0', liefert es '0'. Diese Funktion lässt sich prima verwenden, um bspw. eine einzelne LED blinken zu lassen oder ähnliches, da sie den Zustand eines Pins (oder mehrerer) mit jedem Durchlauf umkehrt.

 

Zurück zur Startseite.