This is an old revision of the document!


Register

Eins der schwersten Dinger die ein Anfänger verstehen kann im Bereich des Microcontrollers ist normalerweise das Register. Wenn man mit Microcontroller arbeitet ist es unmöglich darum zu kommen ohne zu wissen was Register sind. Dieses Buch ist da nicht anders, daher wird vom Leser erwartet sich mit dem Konzept der Register vertraut zu machen, der folgende Text versucht das mit möglichst einfachen Ausdrücken zu beschreiben, damit selbst ein Anfänger eine Idee davon bekommen kann was ein Register ist.

Essence

Tape player's buttons

Ein Register ist wie ein Feld von Knöpfen an einem Haushaltsgerät. Es hat Schalter welche An und Aus geschaltet werden könne. Als bestes Beispiel ist der Videorekorder. Für die, die sich nicht mehr erinnern, der Rekorder hat/hatte sechs Knöpfe, von links nach rechts:

  • Record
  • Rewind
  • Play
  • Fast forward
  • Stop
  • Pause

Jeder Knopf macht etwas bestimmtes, aber nur wenn er korrekt benutzt wird. Zum Beispiel der Stopknopf macht nichts, außer die Kassette spielt gerade – nur dann wird der Knopf etwas bewirken und stoppt die Wiedergabe. Vor- und Zurückspul-Knöpfe, können jederzeit gedrückt werden, weil das Band in beide Richtungen gedreht werden kann, egal ob das Gerät gerade abspielt oder gestoppt ist. Manche haben vielleicht versucht mehrere Knöpfe auf einmal, vielleicht sogar alle auf einmal zu drücken – in diesem Fall hat der Rekorder vielleicht was unvorhergesehenes getan, oder ist sogar kaputt gegangen.

Microcontroller Register verhalten sich wie Knöpfe an einem Videorekorder – jeder Knopf mach etwas Bestimmtes, wenn er richtig benutzt wird. Drückt man den falschen Knopf , wird ein Microcontroller wahrscheinlich nicht kaputt gehen, aber er wird definitiv nicht funktionieren. In Wirklichkeit gibt es keine Knöpfe in den Register, sondern eine Menge an Transistoren, welche den Strom an- und ausstellen. Einfache Microcontroller haben acht Transistor-basierende Schalter in einem Register. Ein Register kann als 8-Bit Nummer gesehen werden, wo jeder Bit durch den Status eines der acht Schalter repräsentiert wird. Zum Beispiel ein Bit mit dem Wert 1 kann bedeuten der Schalter ist an und 0, dass der Schalter aus ist.

Register's “buttons” and bit values

Da der Status der Registerschalter einfach als Nummer dargestellt werden kann und vice versa, kann ein Register mit einem Speicher verglichen werden, der Daten in der Größe einer Nummer halten kann. Mit diesem Vergleich wird deutlich, dass Register eigentlich Speicher-Slots sind. Der Unterschied zwischen Register und Speicher-Slot ist der, dass im Speicher-Slot nur etwas gespeichert wird, aber im Register die Information etwas kontrolliert. Zum Beispiel der Binärwert 01100001 wird in ein Register geschrieben dann werden drei imaginäre Knöpfe gedrückt und etwas Bestimmtes passiert.

An einem Videorekorder ist es möglich jeden Knopf einzeln zu drücken, aber in einem Register ist es schwieriger den Wert eines „Schalters“ oder Bit zu ändern. Normalweise ist es notwendig den gesamten Inhalt des Register zu ändern. Bevor wir zum Ändern des Bit kommen, sollte man wissen, dass es im Microcontroller eine Menge Register gibt. Einige Teile eines Microcontroller benötigen mehr als zehn Register um kontrolliert zu werden. Die Vielfalt der Register bedeutet, dass es einen Weg geben muss, zwischen verschiedenen Registern zu unterscheiden. Das wird gemacht, in dem Man den Registern Namen gibt. Ein Register heißt z.B. PORTB. Eigentlich machen diese Namen es nur einfacherer für die Entwickler, jeder Name hat eine eigene numerische Adresse.

Gebrauch

Um in ein Register zu schreiben, oder den Wert abzulesen, muss er mit einer Variable in C adressiert sein. Das folgende Beispiel demonstriert, wie man einen Binären Wert auf einen imaginären Register REG schreibt und dann die Variable reg ausliest. Binäre Werte werden an einem 0b(leading zero) erkannt, so dass der Compiler das numerische System erkennt

  REG = 0b01100001;
  unsigned char reg = REG;

Es gibt nichts Schwieriges im Schreiben und Lesen von Register Werten, aber es wird ein wenig kniffelig, wenn man nur ein Bit ändern will. Um Bits zu ändern, muss man wissen wie binäre Rechnen funktioniert und unterschiedliche numerische System nutzt. Es ist zwar nicht verboten nur mit binären Nummern zu arbeiten, aber es kann sehr umständlich werden, weil binäre Nummern doch sehr lang werden, und das ist der Grund warum viele Menschen die kürzeren Hexadezimalzahlen nutzen.

Hexadecimal numbers

In Hexadezimal, gibt es nicht nur 0 und 1 wie im Binären, oder 0-9 wie im Dezimalsystem, sondern es geht von 0 bis F. Eine Hexadezimale Zahl besteht aus 4 Bits. Die Tabelle rechts zeigt die Binärzahlen und ihre Hexadezimale Umrechnung. Binäre Zahlen werden zu hexadezimalen Zahlen konvertiert, in dem man 4 Bits auf einmal liest, und am niedrigsten Glied beginnt. Glieder werden von rechts nach links gelesen und starten bei 0, z.B. das niedrigste gegliederte (Glied/Rank 0) Bit ist 0 und das höchste (Glied/Rank 3) ist 1. Im vorhergegangen Beispiel war 01100001 der Binärwert des Registers, welches 61 in hexadezimal ist und wird 0x61 (leading zero) in C geschrieben.

Um ein einzelnes Bit in einer Nummer (Register, Variable oder wo auch immer) ist es notwendig Binäre Operationen zu nutzen. Eine binäre Operation ist eine Operationen zwischen zwei binären Zahlen, wo jeder Bit einer Zahl Objekt einer eigenen logischen Operation ist. Normalerweiser unterstützen Microcontroller vier Binäroperationen, jede mit vielen unterschiedlichen Namen. Der folgende Abschnitt beschreibt die logische Operation hinter den vier binären Operationen mit einem oder mehreren Bits.

Negation, logical multiplication, logical addition and exclusive disjunction

 

  • Negation / Inversion
    Negation changes the bit's value to its opposite, a 0 becomes a 1 and vice versa. In C, negation is marked with “~”.
  • Logical multiplication / Conjunction
    When multiplying two bits, the answer is 1 if both bits are 1 and in any other case 0. In C, logical multiplication is marked with “&”.
  • Logical addition / Disjunction
    When adding two bits, the answer is 1 if at least one of the bits is 1 and 0 if both bits are 0. In C, logical addition is marked with “|”.
  • Exclusive disjunction / Exclusive OR / XOR
    Exclusive OR operation will return 1 if the two bits differ from each other (one is 1 and the other 0), otherwise the answer is 0. In C, exclusive disjunction is marked with “^”.

Dies ist alles was man wissen muss um ein einzelnes Bit zu ändern. Die Theorie ist wahrscheinlich nicht genug und daher gibt’s ein paar typische Beispiele mit Registern in den nächsten Absätzen

Ein einzelnes Bit high setzen

Setting a single bit high

Um einen oder mehrere Bits in einem Register high (1) zu setzen, ist eine logische Addition notwendig. Eine der Rechengrößen muss der Register sein und der andere eine binäre Zahl, wobei nur der high Bit der ist, der im Register auf high gesetzt werden muss. Diese binäre Zahl nennt sich Bitmaske. Unterhalb ist der C-Quellcode für die Operation auf der rechten Seite.

  // Let's suppose REG = 0x0F
  REG = REG | 0x11; // First method
  REG |= 0x11;      // Second method
  // Now REG = 0x1F

Setting a single bit low

Setting a single bit low

Um ein oder mehrere Bits in einem Register low (0) zu setzen, wird eine logische Multiplikationsoperation benötigt. Ein Operand der Operation muss der Register sein, der andere die Bitmaske, in welcher der einzige low Bit der sein muss Unterhalb ist der C- Code für die Operation welche zur Rechten gezeigt wird:

  // Let's suppose REG = 0x0F
  REG = REG & 0xFE; // First method
  REG &= 0xFE;      // Second method
  // Now REG = 0x0E

 

Ein Bit invertieren

Inverting a single bit

Um ein oder mehrere Bits in einem Register zu invertieren ist eine exklusive Trennungsoperation nötig. Einer der Operanden der Operation muss das Register sein, der andere die Bitmaske, wo das einzige High Bit das ist, was im Register invertiert werden soll. Der C-Code für die Operation rechts ist:

  // Let's suppose REG = 0x0F
  REG = REG ^ 0x11; // First method
  REG ^= 0x11;      // Second method (use only one per inversion)
  // Now REG = 0x1E

Das ganze Register invertieren

Inverting all bits

Um alle Bits in einem Register zu invertieren wird eine Inversionsoperation genutzt. Diese Operation ist unär, das bedeutet es hat nur einen Operanden. Unterhalb ist der C-Code für die Operation rechts:

  // Let's suppose REG = 0x0F
  REG = ~REG;
  // Now REG = 0xF0

Den Wert eines einzelnen Bits lesen

Reading the value of a bit

Um einen oder mehrere Bits aus ein Register zu lesen, muss man die gleiche Operation nutzen, als wenn man ein Bit low setzen möchte - logische Multiplikation. Einer der Operanden der Operation ist das Register und der andere ist die Bitmaske, wo der einzige hohe Bit der ist, den man auslesen möchte. Unterhalb ist der C-Code für die Operation rechts:

  // Let's suppose REG = 0x0F
  unsigned char x = REG & 0x01;
  // Now x = 0x01

 

Ein Bit schieben

Viele Programmiersprachen haben ein paar zusätzliche Bitwise Operationen, welche es einfacher für Programmierer machen. Diese sind Bitshift Operationen die Bits nach links oder rechts in einer binären Nummer schieben. Der wichtigste Nutzen für Shiftoperationen ist, wenn man mit Register arbeitet und man Bitranks zu Bitmasken konvertieren will oder anders herum.

Shift left

Das Bild rechts zeigt eine Linksshiftoperation. Auch wenn das Schieben von Bits keine logische Operation ist und kein dazugehöriges Symbol hat, wird es in C mit “«” dargestellt. Ein Linksshift wird genutzt um einen Bit Rank in einer Bitmaske zu transformieren. Zum Beispiel um die Maske für das 6. Bit (Rank 5) zu bekommen muss Nummer 1 5mal nach links geschoben werden. Die Beispiel Operation sieht in C wie folgt aus:

REG = 0x01 << 5;
// Now REG = 0x20
Shift right

Rechtsshiftoperation funktioniert ähnlich wie die Linksshiftoperation. Es wird in C mit “»” dargestellt. Rechtsshift wird benutzt um den logischen Wert eines Bit von der Bitmaske zu bekommen. Ein Beispiel hat gezeigt wie man den Wert eines Bit ließt. Wenn das Bit, dass man lesen möchte, aber nicht den niedrigsten Rank hat, sondern zum Beispiel Rank 5, dann würde das Ergebnis 0x20 oder 0x00 sein, aber manchmal brauch man ein Ergebnis von 1 oder 0. Dann nutzt man einen Rechtsshift. Die Beispieloperation rechts sieht in C wie folgt aus:

// Let's suppose REG = 0x20
unsigned char x = REG >> 5;
// Now x = 0x01 (or simply 1)

Wenn ein Bit vom niedrigsten Rank nach rechts geschoben wird, oder vom höchsten Rank nach links, dann verschwindet es. Eine Programmiersprachen haben rotierende Bitshift Operationen, wo das Bit nicht verschwindet, sondern vom niedrigsten zum höchsten Rank wandert, oder umgekehrt. C hat diese Operation nicht, aber sie kann vom Programmierer selbst geschrieben werden, falls man sie brauch.

Alle Bitoperationen funktionieren nicht nur mit Registern, sondern auch mit Variablen und Konstanten. Die Konstanten können natürlich nur als Operanden genutzt werden.

AVR Register

Um etwas mit einem Register eines Microcontrollers zu machen, muss man wissen wir man diesen Microcontroller benutzt. Jeder Microcontroller kommt mit einem oder mehreren Datenblättern, welche die Struktur und Funktionalität des Microcontrollers beschreiben. Das Datenblatt beschreibt also die Register. Der folgende Absatz wird behilflich sein, die Registerbeschreibung im AVR Datenblatt zu verstehen.

One of AVRs registers from its datasheet

Das Bild zeigt das UCSRnA Register des ATmega128 Microcontrollers. UCSRnA bedeutet “USAR Control und Status Register A”. Das Register wird benutzt um das USART Modul des AVRs zu konfigurieren und den Status auszulesen. Alle AVR Register-Namen werden in Großbuchstaben geschrieben, aber es sollte auffallen dass auch ein kleines n im Namen ist. Ein kleines n markiert den Index eines Moduls. Da der ATmega128 zwei fast identische USART Module hat, werden sie nicht beide beschrieben, aber das n muss als 0 oder 1 vom Nutzer gelesen werden. Daher hat der ATmega128 die Register UCSR0A und UCSR1A.

Der Inhalt des Registers wird durch eine 8-Slot Box mit einer dicken Linie herum markiert. Jeder Slot markiert ein Bit. Bit Ranks weden über der Box markiert - aufsteigend von rechts nach links. Da der AVR ein 8-Bit Microcontroller ist, sind die meisten Register 8-Bit. Es gibt einige Ausnahmen, es gibt 16-Bit Register, aber das sind eigentlich zwei 8-Bit Register. So wie jedes Register einen Namen hat, so hat auch jedes Bit im Register einen Namen - genau wie Knöpfe am Videorekorder. Jedes Bit wird im Datenblatt beschrieben. Bitnamen sind Abkürzungen und die kleinen n müssen mit dem Modulindex übereinstimmen, genau wie bei den Registernamen. Einige Register nutzen weniger als 8-Bit, dann werden die Bitslots mit einem Trennungsstrich markiert.

Unter den Register Bits sind zwei Linien, welche anzeigen ob das Bit Lesbar (R), Beschreibbar (W) oder beides ist (R/W). Zum Beispiel, die Statusbits können nicht überschrieben werden, und selbst wenn es im Programm versucht wird, wird das Bit unverändert bleiben. Wenn das Bit als beschreibbar markiert wurde, wird das auslesen immer in einem spezifischen Wert der im Datenblatt angegeben wird enden. Die zweite Linie gibt den Standardwert des Bit, der Wert den es nach einem Reset des Microcontrollers hat.

Während AVR Registernamen zu einer tatsächlichen Speicherslot Adresse zeigen, haben die Bitnamen die Ranknummer des jeweiligen Bit. Daher ist eine Transformation der Namen zu Bitmasken mit einer Shiftoperation notwendig, wenn man mit Bits in einem Register arbeiten will. Der folgende Code zeit einige Beispielzeilen für die Nutzung des USART 0 Modul Registers.

  // Set TXC0 bit high
  UCSR0A |= (1 << TXC0);
 
  // Set U2X0 bit low
  UCSR0A &= ~(1 << U2X0);
 
  // Read the value of UDRE0 bit(mask)
  unsigned char u = (UCSR0A & (1 << UDRE0));
 
  // At this point u value is either 0 or 32,
  // which enables using it in a logical operation
  if (u)
  {
     // Invert MPCM0 bit
     UCSR0A ^= (1 << MPCM0);
  }
 
  // Sometimes it is necessary to acquire a specific 0 or 1 value,
  // so the read bit needs to be shifted right
  u >>= UDRE0;
 
  // Now the value of u is either 0 or 1
de/avr/registers.1287135905.txt.gz · Last modified: 2020/07/20 09:00 (external edit)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0