Difference between revisions of "AVR Embedded Tutorial - Simple GPIO on and off output/de"

From Free Pascal wiki
Jump to navigationJump to search
m (→‎digitalRead: Changed PORTB to PORTD; PINB to PIND as per other examples)
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Translate}}
+
{{LanguageBar}}
  
 
=Einfache GPIO Ein und Aus-gabe=
 
=Einfache GPIO Ein und Aus-gabe=
  
 
==Direkte Portmanipulation==
 
==Direkte Portmanipulation==
 +
 
Bevor man einen GPIO-Pin auf '''HIGH''' schalten kann, muss man diesen als Ausgang konfigurieren. Dies geht über DDRx.
 
Bevor man einen GPIO-Pin auf '''HIGH''' schalten kann, muss man diesen als Ausgang konfigurieren. Dies geht über DDRx.
 
* Pin auf Ausgabe:
 
* Pin auf Ausgabe:
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
DDRx := DDRx  or (1 shl Pinx);
 
DDRx := DDRx  or (1 shl Pinx);
Line 11: Line 13:
  
 
* Pin auf HIGH:
 
* Pin auf HIGH:
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
PORTx := PORTx or (1 shl Pinx);
 
PORTx := PORTx or (1 shl Pinx);
Line 16: Line 19:
  
 
* Pin auf LOW:
 
* Pin auf LOW:
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
PORTx := PORTx and not (1 shl Pinx);
 
PORTx := PORTx and not (1 shl Pinx);
Line 21: Line 25:
  
 
* Pin umschalten:
 
* Pin umschalten:
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
PORTx := PORTx xor (1 shl Pinx);
 
PORTx := PORTx xor (1 shl Pinx);
Line 28: Line 33:
  
 
Den Status des GPIO-Pins kann man mittels PINx abfragen.
 
Den Status des GPIO-Pins kann man mittels PINx abfragen.
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
if PINx and (1 shl Pinx) > 0 then Pin_ist_HIGH;
 
if PINx and (1 shl Pinx) > 0 then Pin_ist_HIGH;
Line 33: Line 39:
  
 
==Blink-Beispiel==
 
==Blink-Beispiel==
 +
 
Dieses Beispiel zeigt, wie man mit einem ATtiy2313 ein GPIO anspricht.
 
Dieses Beispiel zeigt, wie man mit einem ATtiy2313 ein GPIO anspricht.
 
Dazu werden 2 LEDs an Pin 0 und 1 von PortD angeschlossen.
 
Dazu werden 2 LEDs an Pin 0 und 1 von PortD angeschlossen.
  
 
===Wechselblinker ATtiny2313===
 
===Wechselblinker ATtiny2313===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
program Project1;
 
program Project1;
Line 70: Line 78:
  
 
===Pin Umschalten ATtiny2313===
 
===Pin Umschalten ATtiny2313===
 +
 
Wen man den Pin umschalten will, egal wie sein Ursprungs zustand ist, kann man die mit einer '''xor''' Verknüpfung lösen.
 
Wen man den Pin umschalten will, egal wie sein Ursprungs zustand ist, kann man die mit einer '''xor''' Verknüpfung lösen.
 
Das es auch einen Wechselblinker, wird '''DP0''' zuerst auf HIGH gestellt.
 
Das es auch einen Wechselblinker, wird '''DP0''' zuerst auf HIGH gestellt.
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
begin
 
begin
 
   // Pin 0 und 1 von PortD auf Ausgabe.
 
   // Pin 0 und 1 von PortD auf Ausgabe.
   DDRD := DDRD  or (1 shl DP0) or (1 shl DP1);
+
   DDRD := DDRD  or (1 shl DP0) or (1 shl DP1);
 
   PORTD := PORTD or (1 shl DP0);        // Pin0 ein
 
   PORTD := PORTD or (1 shl DP0);        // Pin0 ein
  
Line 89: Line 99:
  
 
==Vereinfachung Portzugriffe==
 
==Vereinfachung Portzugriffe==
 +
 
Wen man auf Ports zugreift und nicht immer die '''and''', '''or''' und '''xor''' Verknüpfungen schreiben will, kann auch folgende Proceduren/Funktionen verwenden. Die Beispiele zeigen dies für '''PORTD'''. Für andere Ports kann man diese sehr einfach anpassen.
 
Wen man auf Ports zugreift und nicht immer die '''and''', '''or''' und '''xor''' Verknüpfungen schreiben will, kann auch folgende Proceduren/Funktionen verwenden. Die Beispiele zeigen dies für '''PORTD'''. Für andere Ports kann man diese sehr einfach anpassen.
  
 
===pinMode===
 
===pinMode===
 +
 
Entspricht in etwa '''pinMode(...''' von Arduino.
 
Entspricht in etwa '''pinMode(...''' von Arduino.
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
procedure ModePortD(Pin: byte; Value: Boolean);
 
procedure ModePortD(Pin: byte; Value: Boolean);
Line 105: Line 118:
  
 
===digitalWrite===
 
===digitalWrite===
 +
 
Entspricht in etwa '''digitalWrite(...''' von Arduino.
 
Entspricht in etwa '''digitalWrite(...''' von Arduino.
 +
 
<syntaxhighlight lang="pascal">   
 
<syntaxhighlight lang="pascal">   
 
procedure WritePortD(Pin: byte; Value: Boolean);
 
procedure WritePortD(Pin: byte; Value: Boolean);
Line 118: Line 133:
  
 
===digitalSwitch===
 
===digitalSwitch===
 +
 
Schaltet den Pin um, gibt es '''nicht''' beim Arduino.
 
Schaltet den Pin um, gibt es '''nicht''' beim Arduino.
 +
 
<syntaxhighlight lang="pascal">   
 
<syntaxhighlight lang="pascal">   
 
procedure WritePortD(Pin: byte);
 
procedure WritePortD(Pin: byte);
Line 127: Line 144:
  
 
===digitalRead===
 
===digitalRead===
 +
 
Entspricht in etwa '''digitalRead(...''' von Arduino.
 
Entspricht in etwa '''digitalRead(...''' von Arduino.
 +
 
<syntaxhighlight lang="pascal">   
 
<syntaxhighlight lang="pascal">   
function ReadPortB(bit: byte): Boolean;
+
function ReadPortD(bit: byte): Boolean;
 
begin
 
begin
   Result := PINB and (1 shl bit) <> 0;
+
   Result := PIND and (1 shl bit) <> 0;
 
end;   
 
end;   
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
==Pin direkt ansprechen==
 
==Pin direkt ansprechen==
 +
 
Wen man mit '''absolute''' eine '''bitpacked Array''', '''Record''' oder '''Set''' mit dem Port verknüpft, kann man direkt auf jeden Pin zugreifen, ohne lästigen '''or''' und '''and not''' Verknüpfungen.
 
Wen man mit '''absolute''' eine '''bitpacked Array''', '''Record''' oder '''Set''' mit dem Port verknüpft, kann man direkt auf jeden Pin zugreifen, ohne lästigen '''or''' und '''and not''' Verknüpfungen.
  
Line 141: Line 161:
 
Eleganter wird es kaum mehr gehen.
 
Eleganter wird es kaum mehr gehen.
  
Die folgenden drei Beispiele sprechen die ersten 4 Pins von '''PORTD''' an, welche 3 LEDs ansteuern.
+
Die folgenden drei Beispiele sprechen die ersten 4 Pins von '''PORTD''' an, welche 4 LEDs ansteuern.
  
 
===Bitpacked Array===
 
===Bitpacked Array===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
var
 
var
Line 155: Line 176:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
===Bitpacked Record===
  
===Bitpacked Record===
 
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
var
 
var
Line 170: Line 191:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
===Set===
  
===Set===
 
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
var
 
var
Line 181: Line 202:
 
   LEDPortS := LEDPortS - [green, blue] + [red]; // grün, blau aus; rot ein
 
   LEDPortS := LEDPortS - [green, blue] + [red]; // grün, blau aus; rot ein
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
===DDR und PORT===
 +
 +
'''DDR'''x kann man ähnlich lösen, wie bei '''PORT'''x. Dazu am besten die LEDs als '''type''' deklarieren.
 +
 +
<syntaxhighlight lang="pascal">
 +
type
 +
  TLed = bitpacked record
 +
    green, yellow, red, blue: boolean;
 +
  end;
 +
 +
var
 +
  LedPORT: TLed absolute PORTD;
 +
  LedDDR:  TLed absolute DDRD;
 +
 +
begin
 +
  LedDDR.green := True;
 +
  LedDDR.red  := True;
 +
 +
  repeat
 +
    LedPORT.green := True;
 +
    LedPORT.red  := False;
 +
    ...
 +
</syntaxhighlight>
 +
'''PIN'''x kann man ähnlich lösen.
 +
 +
== Arduino Pin PD0 & PD1  ==
 +
 +
Dieser Beschrieb bezieht sich auf den Arduino Uno/Nano, es können auch andere AVRs betroffen sein.
 +
 +
Die Pins '''PD0''' & '''PD1''' von '''PORTD''' werden auch für die '''UART'''-Schnittstelle gebraucht und sind somit blockiert. Wen man diese Pin trotzdem nutzen will, muss man sie wieder frei geben.
 +
 +
<syntaxhighlight lang="pascal">
 +
  UCSR0B := 0;  // UART-Funktionen deaktivieren.
 +
</syntaxhighlight>
 +
 +
'''Hinweis:''' Die LEDs '''RX''' und '''TX''' leuchten negiert, da Anode der LED an Vcc angeschlossen ist.
 +
 +
Genauere Infos über UART hier:
 +
 +
* [[AVR Embedded Tutorial - UART/de|UART]] - Serielle Ein und Ausgabe über UART (COM-Port).
  
 
== Siehe auch ==
 
== Siehe auch ==
* Übersichtseite [[AVR Embedded Tutorial/de]]
 
  
[[Category:Embedded]]
+
* Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
[[Category:AVR]]
+
 
[[Category:Arduino]]
+
Autor: [[User:Mathias|Mathias]]
 +
 
 +
[[Category:AVR/de]]
 +
[[Category:Arduino/de]]
 +
[[Category:Embedded/de]]
 +
[[Category:Tutorials/de]]
 +
{{AutoCategory}}

Latest revision as of 02:19, 26 January 2020

Deutsch (de) English (en)

Einfache GPIO Ein und Aus-gabe

Direkte Portmanipulation

Bevor man einen GPIO-Pin auf HIGH schalten kann, muss man diesen als Ausgang konfigurieren. Dies geht über DDRx.

  • Pin auf Ausgabe:
DDRx := DDRx  or (1 shl Pinx);
  • Pin auf HIGH:
PORTx := PORTx or (1 shl Pinx);
  • Pin auf LOW:
PORTx := PORTx and not (1 shl Pinx);
  • Pin umschalten:
PORTx := PORTx xor (1 shl Pinx);

Lässt man DDRx auf LOW, dann wird mittels PORTx ein PullUp-Widerstand aktiviert. Dies wird gebraucht, um einen Taster gegen GND anzuschließen. Somit kann man auf einen externen PullUp-Widerstand verzichten.

Den Status des GPIO-Pins kann man mittels PINx abfragen.

if PINx and (1 shl Pinx) > 0 then Pin_ist_HIGH;

Blink-Beispiel

Dieses Beispiel zeigt, wie man mit einem ATtiy2313 ein GPIO anspricht. Dazu werden 2 LEDs an Pin 0 und 1 von PortD angeschlossen.

Wechselblinker ATtiny2313

program Project1;
const
  DP0 = 0;      // Pin0 PortD
  DP1 = 1;      // Pin1 PortD
  sl = 150000;  // Verzögerung

  procedure mysleep(t: int32); // Ein einfaches Delay.
  var
    i: Int32;
  begin
    for i := 0 to t do asm nop end;
  end;

begin
  // Pin 0 und 1 von PortD auf Ausgabe.
  DDRD := DDRD  or (1 shl DP0) or (1 shl DP1);

  repeat
    // LED wechseln
    PORTD := PORTD or (1 shl DP0);      // Pin0 ein
    PORTD := PORTD and not (1 shl DP1); // Pin1 aus
    mysleep(sl);                        // Pause

    // LED wechseln
    PORTD := PORTD or (1 shl DP1);      // Pin1 ein
    PORTD := PORTD and not (1 shl DP0); // Pin0 aus
    mysleep(sl);                        // Pause
  until 1 = 2;
end.

Pin Umschalten ATtiny2313

Wen man den Pin umschalten will, egal wie sein Ursprungs zustand ist, kann man die mit einer xor Verknüpfung lösen. Das es auch einen Wechselblinker, wird DP0 zuerst auf HIGH gestellt.

begin
  // Pin 0 und 1 von PortD auf Ausgabe.
  DDRD  := DDRD  or (1 shl DP0) or (1 shl DP1);
  PORTD := PORTD or (1 shl DP0);        // Pin0 ein

  repeat

    // LED wechseln
    PORTD := PORTD xor (1 shl DP0);     // Pin0 umschalten
    PORTD := PORTD xor (1 shl DP1);     // Pin1 umschalten
    mysleep(sl);                        // Pause
  until 1 = 2;
end.

Vereinfachung Portzugriffe

Wen man auf Ports zugreift und nicht immer die and, or und xor Verknüpfungen schreiben will, kann auch folgende Proceduren/Funktionen verwenden. Die Beispiele zeigen dies für PORTD. Für andere Ports kann man diese sehr einfach anpassen.

pinMode

Entspricht in etwa pinMode(... von Arduino.

procedure ModePortD(Pin: byte; Value: Boolean);
begin
  if Value then begin
    DDRD := DDRD or (1 shl Pin);
  end else begin
    DDRD := DDRD and not (1 shl Pin);
  end;
end;

digitalWrite

Entspricht in etwa digitalWrite(... von Arduino.

  
procedure WritePortD(Pin: byte; Value: Boolean);
begin
  if Value then begin
    PORTD := PORTD or (1 shl Pin);
  end else begin
    PORTD := PORTD and not (1 shl Pin);
  end;
end;

digitalSwitch

Schaltet den Pin um, gibt es nicht beim Arduino.

  
procedure WritePortD(Pin: byte);
begin
  PORTD := PORTD xor (1 shl Pin);
end;

digitalRead

Entspricht in etwa digitalRead(... von Arduino.

  
function ReadPortD(bit: byte): Boolean;
begin
  Result := PIND and (1 shl bit) <> 0;
end;

Pin direkt ansprechen

Wen man mit absolute eine bitpacked Array, Record oder Set mit dem Port verknüpft, kann man direkt auf jeden Pin zugreifen, ohne lästigen or und and not Verknüpfungen.

Der kompiliert Code, ist genau gleich gross, wie auf die herkömmliche Methode mit or und and not. Eleganter wird es kaum mehr gehen.

Die folgenden drei Beispiele sprechen die ersten 4 Pins von PORTD an, welche 4 LEDs ansteuern.

Bitpacked Array

var
  LEDPort: bitpacked array [0..7] of boolean absolute PORTD;

begin
  LEDPort[0] := True;
  LEDPort[1] := True;
  LEDPort[2] := False;
  LEDPort[3] := False;

Bitpacked Record

var
  LEDPort: bitpacked record
    red, green, yellow, blue: boolean;
  end absolute PORTD;

begin
  LEDPort.red    := True;
  LEDPort.green  := True;
  LEDPort.yellow := False;
  LEDPort.blue   := False;

Set

var
  LEDPortS: set of (green, yellow, red, blue) absolute PORTD;

begin
  LEDPortS := [yellow, red];                    // gelb, rot ein
  LEDPortS := LEDPortS + [green, blue] - [red]; // grün, blau ein; rot aus
  LEDPortS := LEDPortS - [green, blue] + [red]; // grün, blau aus; rot ein

DDR und PORT

DDRx kann man ähnlich lösen, wie bei PORTx. Dazu am besten die LEDs als type deklarieren.

type
  TLed = bitpacked record
    green, yellow, red, blue: boolean;
  end;

var
  LedPORT: TLed absolute PORTD;
  LedDDR:  TLed absolute DDRD;

begin
  LedDDR.green := True;
  LedDDR.red   := True;

  repeat
    LedPORT.green := True;
    LedPORT.red   := False;
    ...

PINx kann man ähnlich lösen.

Arduino Pin PD0 & PD1

Dieser Beschrieb bezieht sich auf den Arduino Uno/Nano, es können auch andere AVRs betroffen sein.

Die Pins PD0 & PD1 von PORTD werden auch für die UART-Schnittstelle gebraucht und sind somit blockiert. Wen man diese Pin trotzdem nutzen will, muss man sie wieder frei geben.

  UCSR0B := 0;  // UART-Funktionen deaktivieren.

Hinweis: Die LEDs RX und TX leuchten negiert, da Anode der LED an Vcc angeschlossen ist.

Genauere Infos über UART hier:

  • UART - Serielle Ein und Ausgabe über UART (COM-Port).

Siehe auch

Autor: Mathias