Kampis Elektroecke

XMega – I/O

XMega Blockdiagramm

Die I/O wurden mit einigen Zusatzfunktionen ausgestattet, vieles ist aber dennoch identisch zu den 8-Bit AVR. 

Datenrichtungsregister:

Das Datenrichtungsregister bestimmt ob ein Pin als Ausgang oder als Eingang fungiert.
Eine 0x01 bedeutet, dass der dazu gehörige Pin als Ausgang beschaltet ist und eine 0x00 bedeutet, dass er als Eingang arbeitet.
Mit der Codezeile

wird also der komplette PortX als Ausgang gesetzt.
Um einzelne Pins des Datenrichtungsregisters als Ausgang zu schalten, wird die nachfolgende Zeile verwendet.

In dem gezeigten Beispiel wird vom PortX der Pin 0 als Ausgang benutzt und die anderen Pins funktionieren als Eingang.
Chips der XMega Reihe bieten außerdem die Möglichkeit Pins direkt zu togglen.
Dazu gibt es das DIRTLG-Register. Dieses Register beschreibt, welches Bit im Datenrichtungsregister getogglet werden soll.
Als Beispiel:

sagt aus, dass alle Bits im Datenrichtungsregister von PortX getogglet werden sollen. Das heißt, dass jede 0x01 in eine 0x00 umgewandelt wird und umgekehrt.
Schreibt man hingegen

wird nur der Pin 0 im Datenrichtungsregister von PortX getoggled.

Ausgänge schalten und Eingänge einlesen:

Ausgänge:

Wenn ein Pin im Datenrichtungsregister als Ausgang deklariert wurde, kann er durch das Beschreiben des Out-Registers auf High gesetzt werden.
Möchte man z.B. den kompletten PortX auf High setzen schreibt man folgendes:

und will man einen einzelnen Pin (z.B. Pin 0) auf High setzen schreibt man dementsprechend das hier:

Durch den Befehl

wird das Bit gelöscht und der Pin besitzt wieder einen Low Pegel.
Die Ausgänge können außerdem noch über das OUTTGL-Register getoggelt werden.
Um einen kompletten Port zu togglen schreibt man das hier

und für einen einzelnen Pin lautet der Code so

Nun wird der Pin 0 vom PortX getoggled.

Eingänge:

Wurde ein Pin als Eingang deklariert, kann der Status des Pins über das In-Register ausgelesen werden.
Besitzt der Pin einen High Level, steht an der dementsprechenden Stelle im Register eine 0x01 und bei einem Low Level eine 0x00.
Dieser Wert kann anschließend in einer Variable gespeichert werden. Will man z.B. einen Port abfragen und den Wert in einer Variable speichern, schreibt man

Dadurch wird der Wert des In-Registers von PortX in der Variable Port gespeichert.
Wenn ein einzelner Pin nach einem High Pegel abgefragt werden soll, schreibt man dies so

und wenn er nach einem Low Pegel abgefragt werden soll lautet die Zeile so

Pin Control Register

Pull-Up und Pull-Down:

Jeder Pin besitzt ein Pin Control-Register. Mit Hilfe dieses Registers können verschiedene Eigenschaften des Pins eingestellt werden.
Bevor das Register beschrieben wird, empfiehlt sich ein Blick in das XMega A Manual.
Dort wird das Pin Control-Register wie folgt beschrieben:

XMega_IO(1)
Auf Seite 143 dieses Datenblattes gibt es das Bild in der Originalgröße.

Soll nun ein Pin mit einem Pull-Down auf einen Low Pegel gezogen werden, muss entweder eine 0x02 oder eine 0x06 für OPC[2:0] in das Pin Control-Register geschrieben werden (siehe Pull configuration in der Tabelle).
Die Output configuration kann (in diesem Fall) vernachlässigt werden. Wer aber trotzdem wissen möchte was das für Funktionen sind, kann dies im XMegaA Manual nachlesen.
Wenn nun ein Pin mit einem Pull-Down Widerstand versehen werden soll, kann das ganz einfach durch diese Codezeile erledigt werden:

Wenn aber mehrere Pins mit einem Pull-Down versehen werden sollen, empfiehlt sich der Einsatz des MPCMASK-Register.
Mit diesem Register können mehrere Pins eines Portes gleichzeitig z.B. als Ausgang oder als Eingang deklariert werden. Es kann aber auch genutzt werden um die Eigenschaften mehrerer Pins gleichzeitig zu verändern.
Als erstes schreibt man eine Maske in das Register, welche den Pins entspricht die man verändern möchte.
Sollen z. B. Pin 0 und Pin 7 eines Portes verändert werden schreibt man diese Zeile:

Nun ist der Pin 0 und der Pin 7 maskiert. Anschließend legt man noch den Inhalt des Pin Control-Registers fest. Da Pin 0 und Pin 7 mit einem Pull-Down Widerstand versehen werden lautet die nächste Zeile also so:

Nun wird der Pin 0 und der Pin 7 mit einem Pull-Down Widerstand versehen.
Dies kann man natürlich auch für mehrere Pins machen. Wenn z.B. vier Pins mit einem Pull-Up Widerstand versehen werden sollen kann man entweder

schreiben, oder man macht es ein wenig übersichtlicher und verwendet stattdessen eine Maske. Der Code dafür lautet:

Diese zwei Zeilen bewirken genau dasselbe wie die vier Zeilen dadrüber. Nur es sieht ein wenig übersichtlicher aus und vorallem die Pins werden alle gleichzeitig mit einem Pull-Up versehen. Bei den vier Zeilen dadrüber werden die Pins alle einzelnt und nacheinander mit einem Pull-Up versehen.

Invertieren:

Zudem bietet das Pin Control-Register auch die Möglichkeit ein Signal, welches an einem Pin anliegt zu invertieren. Diese Möglichkeit besteht sowohl für Pins die als Ausgang deklariert sind wie auch für Pins die als Eingang funktionieren.
mit dem Befehl

wird vom PortX der Pin 0 invertiert.
Normal wird mit dieser Codezeile

der Pin auf Low gelegt. Dadurch das der Pin aber invertiert ist, liegt der Pegel aber auf High.

Clock and Event Out Register

Ausgabe der Taktfrequenz:

Die XMegas bieten auch noch die Möglichkeit die Taktfrequenz auf einem I/O Pin auszugeben. Zur Auswahl stehen die Pins C7, D7 und E7.
Um die Taktfrequenz auf einen Pin zu legen, muss man ledeglich das CLKEVOUT-Register beschreiben.
Die Bitkombinationen seht ihr auf dem Bild:

XMega_IO(2)

Wenn nun also die Taktfrequenz an C7 ausgegeben werden soll, wird das so gemacht:

Erst wird der Pin C7 als Ausgang definiert und anschließend schreibt man in das CLKEVOUT-Register eine 0x01 um Pin C7 als Taktausgang zu verwenden.

→ Zurück zu AVR

6 Kommentare

  1. Hello there! I know this is somewhat off topic but I was wondering which
    blog platform are you using for this website?

    I’m getting tired of WordPress because I’ve had problems with hackers
    and I’m looking at options for another platform. I would be awesome if you could point me in the direction of a good platform.

  2. Hallo,

    bezüglich “CLKEVOUT”: Kennst du eine Möglichkeit den Clock auf einen andern Pin als Pin7 zu geben? Konkret bräuchte ich das Signal auf PD1. Die PWM steht dabei leider nicht mehr zur Verfügung, weil ich damit schon ein Signal auf PD0 erzeuge.

    Viele Grüße,
    Timo

    1. Hallo Timo,
      laut Datenblatt kann der Takt nur jeweils am Pin 7 ausgegeben werden.
      Kannst du nicht einfach über einen Timer den Pin togglen? So erstellst du auch quasi einen Takt.
      Ich weiß allerdings nicht ob das für dich ausreicht und wie schnell das ganze dann maximal werden kann.

      Gruß
      Daniel

      1. Hallo Daniel,

        daran hatte ich auch gedacht, allerdings wäre das die unsauberste Methode. Ich habe bereits zwei UART- und eine SPI-Schnittstelle auf Interrupts laufen. Da mache ich mir dann schon etwas sorgen um die Sauberkeit des Clocks. In einem Sunny-Day-Szenario müsste das passen. Ich habe einen SysClock von 32MHz, die PWM macht nur 125kHz und an PD1 brauche ich nur 32kHz. Naja, ich werde mich noch etwas umsehen – zur not muss dann das PCB-Design geändert werden ;-)
        Vielen Dank für die schnelle Antwort!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.