2.3 Basic I/O
Der ATmega16 verfügt über vier I/O Ports (PORTA, PORTB, PORTC und PORTD) mit jeweils 8 Pins. Jeder dieser Pins kann als Ein- oder Ausgang konfiguriert werden. Zudem verfügt jeder Pin über Zusatzfunktionen wie Interrupt-Eoingänge, Analog-Digital-Wandler, Timer-Pins und weitere. Hier wird nur die Verwendung der Ports als Ein- und Ausgang beschrieben.
Die Ports sind wie folgt auf die Pins des ATmega16 verteilt:
| Port | Pins |
|---|---|
| PORTA | PA0 - PA7 |
| PORTB | PB0 - PB7 |
| PORTC | PC0 - PC7 |
| PORTD | PD0 - PD7 |
Die Ports sind in 3 Register unterteilt: DDRx, PORTx und PINx. Das DDRx Register wird verwendet, um die Richtung der Pins festzulegen (Eingang oder Ausgang). Das PORTx Register wird verwendet, um die Ausgangswerte der Pins festzulegen. Das PINx Register wird verwendet, um die Eingangswerte der Pins zu lesen. PORTx kommt von "Port Output Register", DDRx von "Data Direction Register" und PINx von "Port Input Register".
Wenn DDRx auf Eingang gesetzt ist, können die Pull-Up Widerstände aktiviert werden, um den Eingang auf HIGH zu setzen, wenn kein Signal anliegt. Dies wird durch das Setzen des entsprechenden Bits im PORTx Register erreicht.
2.3.1 Output
Um einen Pin als Ausgang zu konfigurieren, muss das entsprechende Bit im DDRx Register auf 1 gesetzt werden. Der Ausgangswert des Pins kann dann durch Setzen oder Löschen des entsprechenden Bits im PORTx Register festgelegt werden.
DDRB |= (1 << PB0); // Set PB0 as output
PORTB |= (1 << PB0); // Set PB0 to HIGH
PORTB &= ~(1 << PB0); // Set PB0 to LOW
PORTB |= (1 << PB0) | (1 << PB3); // Set PB0 and PB3 to HIGH
PORTB &= ~((1 << PB0) | (1 << PB3)); // Set PB0 and PB3 to LOW
2.3.2 Input
Um einen Pin als Eingang zu konfigurieren, muss das entsprechende Bit im DDRx Register auf 0 gesetzt werden. Der Eingangswert des Pins kann dann durch Lesen des entsprechenden Bits im PINx Register gelesen werden.
DDRB &= ~(1 << PB0); // Set PB0 as input
if (PINB & (1 << PB0)) // Check if PB0 is HIGH
{
// PB0 is HIGH
}
else
{
// PB0 is LOW
}
2.3.3 Pull-Up Widerstände
Um die Pull-Up Widerstände zu aktivieren, muss das entsprechende Bit im PORTx Register gesetzt werden.
DDRB &= ~(1 << PB0); // Set PB0 as input
PORTB |= (1 << PB0); // Enable pull-up resistor for PB0

Die Pull-up Widerstände sind intern. Sie sorgen für einen definierten Spannungszustand (HIGH) wenn der Ausgang nicht wie in der Abbildung durch das Drücken eines Tasters auf GND gezogen wird.
Zuweisen von Werten zu einem Port
Um den Wert eines Ports zu ändern, kann ein Wert auch direkt zugewiesen werden. Dies ist jedoch nicht empfehlenswert, da dadurch die anderen Bits des Ports überschrieben werden. Zudem wird der Code dadurch unleserlicher. Besser ist es, nur die Bits zu ändern, die geändert werden sollen.
Wenn aber z.B. alle Bits eines Registers oder Ports gesetzt werden sollen, gibt es verschieden Möglichkeiten:
PORTB = 0b00001111; // Set PORTB to 0b00001111
PORTB = 0xF3; // Set PORTB to 0xF3
PORTB = O123; // Set PORTB to octal 123
PORTB = 123; // Set PORTB to decimal 123