diyundso.de

Grundlagen AVR-GCC

Standard-Includes

#include <avr/io.h> //Bezeichnungen für Register/Bits

Ausgänge

Soll z.B. der Pin PD4 des AVRs als Ausgang benutzt werden, muss der PIN zunächst im Register DDRD (bei PB2 wäre es dann DDRB usw.) als solcher definiert werden. Dazu wird das 4. Bit von DDRD gesetzt:

DDRD |= (1<<4);


PD4 ist nun ein Ausgang. Um einen HIGH-Level an PD4 zu erzeugen, muss nun das 4. Bit von PORTD gesetzt werden:

PORTD |= (1<<4);


Analog dazu lässt sich auch ein LOW-Level an PD4 erzeugen, dazu muss das 4. Bit von PORTD gelöscht werden:

PORTD &= ~(1<<4);

Eingänge

Soll z.B. der Pin PD4 des AVRs als Eingang benutzt werden, muss der PIN zunächst im Register DDRD (bei PB2 wäre es dann DDRB usw.) als solcher definiert werden. Dazu wird das 4. Bit von DDRD gelöscht:

DDRD &= ~(1<<4);


PD4 ist nun ein Eingang. Um den internen Pullup-Widerstand des AVR an PD4 zu nutzen, muss nun das 4. Bit von PORTD gesetzt werden:

PORTD |= (1<<4);


Ob der Status von PD4 nun HIGH oder LOW ist, lässt sich aus dem 4. Bit des Registers PIND auslesen:

if ( PIND & (1<<4) ){//Status ist HIGH
//...
}

if ( !(PIND & (1<<4) ) ){//Status ist LOW
//...
}

Funktionsweise des Auslesevorgangs (kein Code!)

z.B. PIND = 10010001


ausführen von PIND & (1<<4):

1 = 00000001


Linksshift von 1 um 4 stellen:

(1<<4) = 00010000


verUNDen des PIND-Wertes mit (1<<4):

10010001 & 00010000 = 00010000 //Das Ergebnis ist 16


Da 16 ungleich 0, ist die Bedingung: (PIND&(1<<4)) wahr.

Wird nun PD4 z.B. durch einen Taster auf LOW-Level gezogen, so wird ( PIND & (1<<4) ) zu 0, also falsch.
Die Verneinung ( !( PIND & (1<<4) ) ) ist dann also wahr.

Bitmanipulationen

Bits setzen und löschen

Oben wurde bereits gezeigt wie ein Bit gesetzt/gelöscht wird, hier wird dies noch um das Umschalten eines Bits (toggeln) ergänzt und anschließend genauer erklärt:

DDRD |= (1<<4); //4. Bit setzen

DDRD &= ~(1<<4); //4. Bit löschen

DDRD ^= (1<<4); //4. Bit toggeln

Funktionsweise Bit setzen (kein Code!)

z.B. DDRD = 00100101


ausführen von DDRD |= (1<<4):

1 = 00000001


Linksshift von 1 um 4 stellen:

(1<<4) = 00010000


verODERn des DDRD-Wertes mit (1<<4):

00100101 | 00010000 = 00110101 //4. Bit nun 1


Neuen Wert in das Register DDRD schreiben:

DDRD = DDRD | (1<<4);
DDRD |= (1<<4); //kürzere Schreibweise

Funktionsweise Bit löschen (kein Code!)

z.B. DDRD = 00100101


ausführen von DDRD &= ~(1<<2):

1 = 00000001


Linksshift von 1 um 2 stellen:

(1<<2) = 00000100


Negieren von (1<<2):

~(1<<2) = 11111011


verUNDen des DDRD-Wertes mit ~(1<<2):

00100101 | 11111011 = 00100001 //2. Bit nun 0


Neuen Wert in das Register DDRD schreiben:

DDRD = DDRD & ~(1<<2);
DDRD &= ~(1<<2); //kürzere Schreibweise

Funktionsweise Bit toggeln (kein Code!)

z.B. DDRD = 00100101


ausführen von DDRD ^= (1<<2):

1 = 00000001


Linksshift von 1 um 2 stellen:

(1<<2) = 00000100


verXORen des DDRD-Wertes mit (1<<2):

00100101 | 00000100 = 00100001 //2. Bit nun getoggelt


Neuen Wert in das Register DDRD schreiben:

DDRD = DDRD ^ (1<<4);
DDRD ^= (1<<4); //kürzere Schreibweise

Delays

#define F_CPU 1000000 //CPU-Takt angeben in Hz
#include <util/delay.h>

_delay_ms(100); //100ms Delay
_delay_us(100); //100µs Delay

Beispielcode: PD2 in Endlosschleife an- und ausschalten:

#include <avr/io.h>
#define F_CPU 1000000 //hier CPU-Takt in Hz eintragen
#include <util/delay.h>

int main (void){

DDRD |= (1<<2); //PD2 als Ausgang

while(1){ //Endlosschleife

PORTD ^= (1<<2);
_delay_ms(1000); //Status von PD2 soll alle 1000ms von HIGH auf LOW und umgekehrt wechseln.

}

return 0; }
Impressum

Valid HTML 4.01 Transitional