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

Pull-up Widerstand

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