Allgemeiner Zugriff auf Register

Die AVR-Controller verfügen über eine Vielzahl von Registern. Die meisten davon sind sogenannte Schreib-/Leseregister. Das heisst, das Programm kann die Inhalte der Register auslesen und beschreiben.
Einige Register haben spezielle Funktionen, andere wiederum könne für allgemeine Zwecke (Speichern von Datenwerten) verwendet werden.

Einzelne Register sind bei allen AVR's vorhanden, andere wiederum nur bei bestimmten Typen. So sind beispielsweise die Register, welche für den Zugriff auf den UART notwendig sind selbstverständlich nur bei denjenigen Modellen vorhanden, welche über einen UART verfügen.

Die Namen der Register sind in den Headerdateien zu den entsprechenden AVR-Typen definiert.
Wenn im Makefile der MCU-Typ definiert ist so bindet das System automatisch die richtige Headerdatei ein.
Man kann der MCU-Typ aber selbstverständlich auch noch in der C-Quelldatei definieren, wenn man Freude daran hat.

I/O-Register

Die I/O-Register haben einen besonderen Stellenwert bei den AVR Controllern. Sie dienen dem Zugriff auf die Ports und die Schnittstellen des Controllers.
Wir unterscheiden zwischen 8-Bit und 16-Bit Registern. Vorerst behandeln wir mal die 8-Bit Register.

Lesen eines I/O-Registers

Der gesamte Inhalt eines Registers kann mit dem Befehl

inp(<register>);

ausgelesen werden.

Lesen eines Bits

Die AVR-Bibliothek stellt auch Funktionen zur Abfrage eines einzelnen Bits eines Registers zur Verfügung:

bit_is_set (<port>, <pin>);

Die Funktion bit_is_set prüft, ob ein Bit gesetzt ist. Wenn das Bit gesetzt ist wird ein Wert ungleich 0 zurückgegeben. Genau genommen ist es die Wertigkeit des abgefragten Bits, also 1 für Bit0, 2 für Bit1, 4 für Bit2 etc.

bit_is_clear (<port>, <pin>);

Die Funktion bit_is_clear prüft, ob ein Bit gelöscht ist. Wenn das Bit gelöscht ist, also auf 0 ist, wird ein Wert ungleich 0 zurückgegeben.

Schreiben eines I/O-Registers

Zum Beschreiben eines I/O-Registers verwendet man allgemein den Befehl

outp (<wert>, <register>);

Als Wert muss die Bitmaske mit den Werten aller Pins angegeben werden.

Schreiben eines Bits

Auch für das Setzen bzw. Löschen eines einzelnen Bits eines I/O-Registers stellt die AVR-Bibliothek entsprechende Funktionen zur Verfügung.

sbi (<register>, <bitnummer>);

Die Funktion sbi setzt ein beliebiges Bit eines Registers, das heisst, es wird der logische Wert 1 in das Bit geschrieben. Die anderen Bits des Ports werden nicht verändert.
Das niederwertigste Bit hat die Bitnummer 0.

cbi (<register>, <bitnummer>);

Die Funktion cbi löscht ein beliebiges Bit eines Registers, das heisst, es wird der logische Wert 0 in das Bit geschrieben. Die anderen Bits des Ports werden nicht verändert.
Das niederwertigste Bit hat die Bitnummer 0.

Warten auf einen bestimmten Zustand

Es gibt in der Bibliothek sogar Funktionen, die Warten, bis ein bestimmter Zustand auf einem Bit erreicht ist.
Es ist allerdings normalerweise eine eher unschöne Programmiertechnik.

loop_until_bit_is_set(<register>, <bitnummer>);

Die Funktion loop_until_bit_is_set wartet in einer Schleife, bis das definierte Bit gesetzt ist. Wenn das Bit beim Aufruf der Funktion bereits gesetzt ist wird die Funktion sofort wieder verlassen.
Das niederwertigste Bit hat die Bitnummer 0.

loop_until_bit_is_clear(<register>, <bitnummer>);

Die Funktion loop_until_bit_is_clear wartet in einer Schleife, bis das definierte Bit gelöscht ist. Wenn das Bit beim Aufruf der Funktion bereits gelöscht ist wird die Funktion sofort wieder verlassen.
Das niederwertigste Bit hat die Bitnummer 0.