Programmierung des Mikrocontrollers mit C



2. Digitale Ausgänge des Mikrocontrollers benutzen

Betrachten wir einmal die Pinbelegung eines Atmega8:

pinout

Als digitale Ausgänge können wir all die Anschlußpins benutzen, die da heißen: PB0 bis PB7, PC0 bis PC6 und PD0 bis PD7.
Es handelt hierbei um sogenannte Ports. Vielleicht erinnert Dich das Wort "Port" an einen Hafen, wo die Schiffe ein- und ausfahren - das ist gar nicht mal so falsch.

Unser Atmega8 hat drei Ports, nämlich Port B, Port C und Port D.

So ein Port hat gewöhnlich 8 Anschlüsse (nur beim Atmega8 hat der Port C wegen Platzmangels lediglich 7 Anschlüsse).
Der Port B hat die Anschlüsse PB0, PB1, PB2, PB3, PB4, PB5, PB6 und PB7.
Der Port C hat die Anschlüsse PC0, PC1, PC2, PC3, PC4, PC5 und PC6.
Der Port D hat die Anschlüsse PD0, PD1, PD2, PD3, PD4, PD5, PD6 und PD7.
Diese Anschlüsse kann man als digitale Ausgänge oder als digitale Eingänge benutzen.

Mann kann auch noch mehr damit machen. Wie Du siehst, sind dort an den Anschlüssen noch Bezeichnungen in Klammern.

Nehmen wir einmal PB0 bis PB7. Diese Beinchen gehören zum PORT B.
Zu diesem PORT B gehört außerdem das Datenrichtungsregister DDR B (data direction register B).

Ein Register ist im Prinzip eine Aneinanderreihung einiger Speicherzellen (z. B. 8 bit).

irgendein Register:
7. bit 6. bit 5. bit 4. bit 3. bit 2. bit 1. bit 0. bit

Wenn PB0 (also Anschlußbeinchen 14 des Atmega8) ein Ausgang sein soll, dann muß im Datenrichtungsregister DDRB das 0. bit gesetzt sein, so wie hier:

DDRB:
0
0 0 0
0
0
0
1

Das Datenrichtungsregister legt fest, ob’s rein (Eingang) oder raus (Ausgang) gehen soll. Wenn PB0 ein Ausgang sein soll, muß im Datenrichtungsregister B das nullte Bit gesetzt sein. In der Programmiersprache C geht das z. B. so: DDRB = 1;

Sollen PB0 und PB1 Ausgänge sein, ginge es mit: DDRB = 3;

Warum 3? Eine 3 in Binärzahlenschreibweise sieht so aus: 00000011
Das nullte und das erste Bit sind somit gesetzt (man zählt von rechts!).

Soll nun der Ausgang PB0 auf HIGH gesetzt werden, geht das mit: PORTB = 1;
Soll der Ausgang PB0 auf LOW gesetzt werden, geht das mit: PORTB = 0;

Eine am PB0 angeschlossene LED würde nun an und aus gehen - allerdings so schnell, dass man es nicht mehr sehen könnte.
Darum enthält das nun folgende komplette Programm Verzögerungen (engl. delay), was wir erst später kennenlernen.


#include <avr/io.h>

#define F_CPU 1000000UL // 1 MHz

#include <avr/delay.h>


int main(void){

    DDRB=1; // damit ist dann PB0 ein Ausgang

    while(1){

        PORTB = 1; //0. bit im Port B setzen
        _delay_ms(250); //warte 250 ms

        PORTB = 0; //0. bit im Port B löschen
        _delay_ms(250);//warte 250 ms

    }

return(0);

}


Was macht das Programm?


Damit Anschlußpin 14 des Atmega8 (also PB0) ein Ausgang ist, haben wir dem Datenrichtungsregister des Port B das nullte Bit gesetzt:   DDRB=1;

DDRB:
0
0 0 0
0
0
0
1


Damit Anschlußpin 14 des Atmega8 (also PB0) HIGH ausgibt (also 5V), haben wir im Port B das nullte Bit (also PB0)
gesetzt:   PORTB=1;

PORTB:
0
0 0 0
0
0
0
1

Dann haben wir 250 Millisekunden gewartet.


Damit Anschlußpin 14 des Atmega8 (also PB0) LOW ausgibt (also 0V), haben wir im Port B das nullte Bit (also PB0) wieder gelöscht:   PORTB=0;

PORTB:
0
0 0 0
0
0
0
0

Dann haben wir wieder 250 Millisekunden gewartet.


Das Setzen und Löschen des 0. Bits im Port B erfolgt in einer endlos laufenden Schleife.
Du erinnerst Dich:
    
  while(1){
    // --- diese Schleife endet nie ---    
  }


weiter