| Next revision | Previous revision |
| de:avr:registers [2010/06/30 17:07] – angelegt Wember | de:avr:registers [2020/07/20 09:00] (current) – external edit 127.0.0.1 |
|---|
| ====== Registers ====== | ====== 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. | Typischerweise ist das Register eines der Bestandteile eines Mikrocontrollers, die ein Anfänger nur mühsam versteht. Im Umgang mit Mikrocontrollern ist es jedoch unumgänglich diese Komponente zu kennen. Auch für die weitere Arbeit mit diesem Buch ist der Leser dazu angehalten, sich das Konzept des Registers anzueignen. Daher wird es im nun folgenden Text auf eine möglichst verständliche Weise erklärt, sodass auch ein Anfänger ein Gespür für das Register bekommt. |
| |
| ===== Essence ===== | ===== Essence ===== |
| |
| [{{ :images:logic:tape_buttons.jpg?240|Tape player's buttons}}] | [{{ :images:logic:tape_buttons.jpg?240|Tasten eines Kassettenrekorders}}] |
| |
| 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. | Ein Register ähnelt einem Panel von Tasten eines Haushaltsgerätes. Es verfügt über Schalter, die ein- und ausgeschaltet werden können. Das beste Beispiel hierfür ist ein Kassettenrekorder. Zur Erinnerung, ein Kassettenrekorder verfügt über 6 Tasten von links nach rechts: |
| Für die, die sich nicht mehr erinnern, der Rekorder hat/hatte sechs Knöpfe, von links nach rechts: | |
| |
| |
| * Record | * Aufnahme |
| * Rewind | * Zurückspulen |
| * Play | * Abspielen |
| * Fast forward | * Vorspulen |
| * Stop | * Stopp |
| * Pause | * Pause |
| |
| Jeder Knopf macht etwas bestimmtes, aber nur wenn er korrekt benutzt wird. Zum Beispiel der Stopknopf macht nichts, außer die Kassette spielt grade – 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 grade 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 unvorhergesehendes getan, oder ist sogar kaputt gegangen. | Jede Taste führt eine Funktion aus, jedoch nur wenn sie auch korrekt verwendet wird. So macht die Stopp-Taste solange nichts, bis die Kassette abgespielt wird. Erst dann kann die Funktion ausgeführt werden und die Wiedergabe wird gestoppt. Dagegen können Vorlauf- und Rückspultasten zu jeder Zeit betätigt werden, denn die Kassette kann in beide Richtungen gespult werden, unabhängig davon ob sie gerade abgespielt wird oder nicht. Die Aufnahmetaste startet nur dann eine Aufnahme, wenn sowohl die Abspielen- als auch die Aufnahmetaste zeitgleich gedrückt werden. Eventuell hat mancher einmal versucht, mehrere oder alle Tasten auf einmal zu betätigen. Dieses hat vermutlich eine unerwartete Funktion des Kassettenrekorders ausgelöst oder ihn sogar beschädigt. |
| |
| 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. | Die Register von Mikrocontrollern verhalten sich wie Tasten eines Kassettenrekorders – jede Taste führt eine Funktion aus, wenn sie korrekt verwendet wird. Werden die falschen Tasten betätigt, wird der Mikrocontroller in der Regel nicht direkt beschädigt, aber er wird nicht funktionieren. Tatsächlich gibt es keine Tasten im Register sondern stattdessen eine Vielzahl von Transistoren, welche die Stromversorgung ein- und ausschalten. Einfachere Mikrocontroller haben 8 transistorbasierte Schalter in einem einzigen Register. Unter einem Register kann man sich eine 8-Bit Zahlenfolge vorstellen, wobei jedes Bit durch den Status eines dieser Schalter gekennzeichnet wird. Zum Beispiel kann ein Bit-Wert von 1 bedeuten, dass der Schalter an ist, ein Wert von 0 hieße dann, dass er aus ist. |
| Zum Beispiel ein Bit mit dem Wert 1 kann bedeuten der Schalter ist an und 0, dass der Schalter aus ist. | |
| |
| | [{{ :images:logic:register_buttons_and_bits.png?240|"Tasten" des Registers und Bitwerte}}] |
| |
| [{{ :images:logic:register_buttons_and_bits.png?240|Register's "buttons" and bit values}}] | Da der Status eines Registerschalters einfach durch eine Nummer abgebildet werden kann, lässt sich ein Register mit einem Speicher vergleichen, der Daten in Form genau einer Zahl speichern kann. Durch diesen Vergleich wird deutlich, dass Register tatsächlich Speicherslots sind. Der Unterschied zwischen einem Register und einem Speicherslot besteht darin, dass letzterer lediglich Informationen speichert, während die Informationen in einem Register tatsächlich etwas steuern. So sorgt zum Beispiel der Binärwert 01100001 in einem Register dafür, dass drei imaginäre Tasten betätigt werden wodurch eine Funktion ausgelöst wird. |
| |
| 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 SpeicherSlots 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. | |
| |
| | Während es bei einem Kassettenrekorder möglich ist, jeden Knopf einzeln zu betätigen, ergeben sich bei einem Register Schwierigkeiten, wenn nur der Wert eines Schalters oder Bits geändert werden soll. Hier ist es gewöhnlich notwendig, den gesamten Inhalt der Registers zu ändern. Bevor jedoch detaillierter auf die Thematik der Bit-Veränderung eingegangen wird, muss zunächst klargestellt werden, dass ein Mikrocontroller mehrere Register enthält. Die Vielzahl der Register führt dazu, dass diese voneinander unterscheidbar gemacht werden müssen, was durch Kennzeichnung mit einem Namen geschieht, wie zum Beispiel „PORTB“. Hierdurch wird dem Entwickler die Arbeit erleichtert, da jedem Namen auch eine eigene numerische Adresse zugewiesen wird. |
| |
| 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. | ===== Gebrauch ===== |
| 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 Addresse. | |
| |
| | Zur Programmierung eines Registers oder auch dazu, um Werte aus diesem abzulesen muss er als Variable in C deklariert werden. Das folgende Beispiel veranschaulicht, wie ein Binärwert einem imaginären Register REG zugewiesen wird und dann in der Variable //reg// abgelegt wird. Binärwerte werden an einem vorangestellten 0b (leading zero) erkannt, sodass der Compiler das binäre Zahlensystem erkennt. |
| ===== Usage ===== | |
| | |
| Um auf 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 | |
| |
| <code c> | <code c> |
| </code> | </code> |
| |
| 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. | Die Schwierigkeit liegt nicht darin, Registerwerte zu schreiben und auszulesen, sondern vielmehr darin, ein einzelnes Bit zu verändern. Hierzu sind Kenntnisse der Binärmathematik sowie im Gebrauch diverser Zahlensysteme notwendig. Es ist auch möglich, nur mit Binärzahlen zu arbeiten. Da diese aufgrund ihrer Länge die Programmierarbeit jedoch erschweren können, verwenden die meisten Programmierer die kürzeren Hexadezimalzahlen. |
| |
| [{{ :images:logic:logic_hexadecimal.png?209|Hexadecimal numbers}}] | [{{ :images:logic:logic_hexadecimal.png?209|Hexadezimalzahlen}}] |
| |
| In hexadecimal, the numbers are not only 0 and 1 as in binary or 0 to 9 as in decimal, but instead 0 to F. A hexadecimal number consists of four bits. The table on the right shows the binary numbers and their hexadecimal counterparts. Binary numbers are converted to hexadecimal by reading bits four at a time, starting from the lowest rank. Ranks are read from right to left and their numbers start from 0. For example, the lowest ranked (rank 0) bit is 0 and the highest (rank 3) is 1. In the previous example, the register's binary value is 01100001, which is 61 in hexadecimal and is written as 0x61 (leading zero) in C. | Im Hexadezimalsystem gibt es nicht nur die Ziffern 0 und 1 wie im binären System oder 0 bis 9 gemäß dem Dezimalsystem, sondern stattdessen 0 bis F. Eine Hexadezimalzahl besteht aus vier Bits. Die Abbildung auf der rechten Seite veranschaulicht die Binärzahlen und deren zugehörige Hexadezimalwerte. Binärzahlen werden in Hexadezimalzahlen umgewandelt indem vier Bits zugleich, beginnend bei dem niedrigsten, gelesen werden. Die Bitfolge wird von links nach rechts gelesen und startet bei 0. So ist zum Beispiel das niederwertigste Bit (an Stelle 0) 0 und das mit dem höchsten Wert (an Stelle 3) 1. Im vorangehenden Beispiel ist der Binärwert der Registers 01100001, der im Hexadezimalsystem 61 entspricht und in C als 0x61 (leading zero) geschrieben wird. |
| |
| To change single bits in a number (register, variable or anywhere else for that matter) it is necessary to use binary operations. Binary operation is an operation between two binary numbers, where each bit of the numbers is subject to its own logical operation. Typically a microcontroller supports four binary operations, each having several names. The following section describes the logical operation behind each of these four binary operations with a single bit or multpile bits. | Um einzelne Bits innerhalb einer Zahl zu verändern (Register, Variable oder ähnliches) müssen Binäroperationen angewandt werden. Binäroperationen sind Vorgänge zwischen zwei Binärzahlen, wobei jedes Bit der Zahlen durch eine eigene logische Operation abgebildet wird. Mikrocontroller unterstützen generell vier unterschiedliche Binäroperationen. Der folgende Abschnitt beschreibt die logische Operation hinter diesen vier Binäroperationen mit einzelnen sowie mehreren Bits. |
| |
| [{{ :images:logic:logic_all_4.png?550 |Negation, logical multiplication, logical addition and exclusive disjunction }}] | [{{ :images:logic:logic_all_4.png?550 |Negation, logische Multiplikation, logische Addition und exklusive Disjunktion }}] |
| |
| ~~PB~~ | <pagebreak> |
| |
| * **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 "~". | * **Negation / Inversion** \\ Eine Negation kehrt den Wert eines Bits in das jeweilige Gegenteil um. So wird aus einer 0 eine 1 und umgekehrt. In C wird eine Negation durch "~" vorgenommen. |
| * **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 "&". | * **Logische Multiplikation / Konjunktion** \\ Bei der Multiplikation zweier Bits ist das Ergebnis 1 für den Fall, dass beide Bits den Wert 1 besitzen, ansonsten 0. Eine Logische Multiplikation wird in C durch "&" dargestellt. |
| * **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 "|". | * **Logische Addition / Disjunktion** \\ Eine Addition von zwei Bits ergibt 1 wenn zumindest eines der Bits den Wert 1 hat und 0 wenn beide Bits den Wert 0 haben. In C kennzeichnet "|" die Logische Addition. |
| * **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 "^". | * **Exklusive Disjunktion / Exklusives ODER / XOR** \\ Das Ergebnis einer Exklusiven ODER Operation ist 1 bei zwei unterschiedlichen Bits (also wenn ein Bit den Wert 1 besitzt, das andere den Wert 0), ansonsten 0. Eine Exklusive Disjunktion wird in C durch "^" dargestellt. |
| |
| This is all one needs to know to change single bits. The theory alone is probably not enough, though, and that is why there are some typical examples with registers in the next few paragraphs. | Man benötigt nicht mehr als diese vier Operationen, um einzelne Bits zu ändern. Da die Theorie allein vermutlich nicht ausreichen mag, enthalten die folgenden Abschnitte einige Anwendungsbeispiele. |
| |
| ~~CL~~ | ~~CL~~ |
| |
| ==== Setting a single bit high ==== | ==== Ein einzelnes Bit "high" setzen ==== |
| |
| [{{ :images:logic:op_bit_set.png?230|Setting a single bit high}}] | [{{ :images:logic:op_bit_set.png?230|Ein einzelnes Bit "high" setzen}}] |
| |
| To set one or more bits in a register high (1) a logical addition operation is needed. One of the operands of the operation must be the register and the other a binary number, where the only high bit is the one that needs to be set high in the register. This binary number is called a bitmask. Below is the C code for the operation shown on the right: | Um einzelne oder mehrere Bits in einem Register “high” zu setzen (1) muss eine logische Addition durchgeführt werden. Hierfür muss ein Operand das Register sein und ein anderer die Binärzahl, wobei das einzige „high“ Bit jenes ist, was ein einem Register „high“ gesetzt werden muss. Diese Binärzahl wird Bitmaske genannt. Nachfolgend ist der C-Code für diese Operation abgebildet: |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x0F | // Annahme REG = 0x0F |
| REG = REG | 0x11; // First method | REG = REG | 0x11; // Erste Methode |
| REG |= 0x11; // Second method | REG |= 0x11; // Zweite Methode |
| // Now REG = 0x1F | // Ergebnis REG = 0x1F |
| </code> | </code> |
| |
| ==== Setting a single bit low ==== | ==== Ein einzelnes Bit “low” setzen ==== |
| |
| [{{ :images:logic:op_bit_clear.png?229|Setting a single bit low}}] | [{{ :images:logic:op_bit_clear.png?229|Ein einzelnes Bit “low” setzen}}] |
| |
| To set one or more bits in a register low (0) a logical multiplication operation is needed. One operand of the operation must be the register and the other a bitmask, in which the only low bit is the one that needs to be set low in the register. Below is the C code for the operation shown on the right: | Um einzelne oder mehrere Bits in einem Register “low“ zu setzen (0) ist eine logische Multiplikation nötig. Dabei muss ein Operand das Register und ein weiterer eine Bitmaske sein, in welcher das einzige low-Bit jenes ist, welches im Register „low“ gesetzt werden soll. |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x0F | // Annahme REG = 0x0F |
| REG = REG & 0xFE; // First method | REG = REG & 0xFE; // Erste Methode |
| REG &= 0xFE; // Second method | REG &= 0xFE; // Zweite Methode |
| // Now REG = 0x0E | // Ergebnis REG = 0x0E |
| </code> | </code> |
| |
| ~~PB~~ | <pagebreak> |
| |
| ==== Inverting a single bit ==== | ==== Ein einzelnes Bit invertieren / umkehren ==== |
| |
| [{{ :images:logic:op_bit_invert.png?229|Inverting a single bit}}] | [{{ :images:logic:op_bit_invert.png?229|in einzelnes Bit invertieren}}] |
| |
| To invert one or more bits in a register an exclusive disjunction operation is required. One of the operands of the operation must be the register and the other a bitmask, where the only high bit is the one that needs to be inverted in the register. Below is the C code for the operation shown on the right: | Zum Invertieren einzelner oder mehrerer Bits eines Registers muss eine Exklusive Disjunktion angewandt werden. Hierzu ist ein Operand das Register, der andere muss eine Bitmaske sein, in der das einzige high Bit jenes ist, welches invertiert werden soll. Der C-Code für diese Operation ist unten abgebildet: |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x0F | // Annahme REG = 0x0F |
| REG = REG ^ 0x11; // First method | REG = REG ^ 0x11; // Erste Methode |
| REG ^= 0x11; // Second method (use only one per inversion) | REG ^= 0x11; // Zweite Methode (nur eine pro Inversion verwenden) |
| // Now REG = 0x1E | // Ergebnis REG = 0x1E |
| </code> | </code> |
| |
| ==== Inverting the whole register ==== | ==== Das gesamte Register invertieren ==== |
| |
| [{{ :images:logic:op_reg_invert.png?229|Inverting all bits}}] | [{{ :images:logic:op_reg_invert.png?229|Invertieren aller Bits}}] |
| | |
| | Durch die Negationsoperation werden sämtliche Bits eines Register invertiert. Diese Operation besteht aus nur einen Operanden und ist daher unär. Der hierfür benötigte C-Code ist unten abgebildet: |
| |
| To invert all bits in a register a negation operation is used. This operation is unary, which means it has only one operand. Below is the C code for the operation shown on the right: | |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x0F | // Annahme REG = 0x0F |
| REG = ~REG; | REG = ~REG; |
| // Now REG = 0xF0 | // Ergebnis REG = 0xF0 |
| </code> | </code> |
| |
| ==== Reading the value of a single bit ==== | ==== Den Wert eines einzelnen Bits auslesen ==== |
| | |
| | [{{ :images:logic:op_bit_get.png?229|Den Wert eines Bits auslesen}}] |
| |
| [{{ :images:logic:op_bit_get.png?229|Reading the value of a bit}}] | Sollen ein oder mehrere Bits aus einem Register gelesen werden muss ebenfalls die logische Multiplikation angewandt werden. Einer der Operanden ist das Register, der zweite eine Bitmaske, in welcher das einzige high-Bit jenes ist, welches aus dem Register gelesen werden soll. Unten ist der C-Code für diesen Vorgang dargestellt. |
| |
| To read one or more bits from a register the same operation is required as was used for setting a bit low - logical multiplication. One of the operands of the operation must be the register and the other a bitmask, where the only high bit is the one that needs to be read from the register. Below is the C code for the operation shown on the right: | |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x0F | // Annahme REG = 0x0F |
| unsigned char x = REG & 0x01; | unsigned char x = REG & 0x01; |
| // Now x = 0x01 | // Ergebnis x = 0x01 |
| </code> | </code> |
| |
| ~~PB~~ | <pagebreak> |
| |
| ==== Shifting a bit ==== | ==== Ein Bit verschieben ==== |
| |
| Many programming languages actually have a few additional bitwise operations, which make it easier for the programmers. These are bit shifting operations that shift bits left or right in a binary number. The main value of shift operations in dealing with registers is their ability to convert bit ranks to bitmasks and vice versa. | Viele Programmiersprachen verfügen mittlerweile über einige zusätzliche Bitoperationen, was die Programmierarbeit erleichtert. Hierzu gehören die Operationen, welche die Bits einer Binärzahl nach rechts oder links verschieben. Im Umgang mit Registern liegt der größte Vorteil dieser Operationen darin, dass Bitfolgen zu Bitmasken konvertiert werden können und umgekehrt. |
| |
| [{{ :images:logic:op_bit_shift_left.png?241|Shift left}}] | [{{ :images:logic:op_bit_shift_left.png?241|Linksshift}}] |
| |
| The image on the right shows a shift left operation. Although bit shifting is not a logical operation and has no corresponding symbol, in C it is marked as "<<". Shift left is used to transform a bit rank to a bitmask. For example, to get the mask for the 6th bit (NB! rank 5), number 1 has to be shifted left 5 times. The example operation looks like this in C: | Das Bild auf der rechten Seite zeigt einen Linksshift. Auch wenn ein Bitshift keine logische Operation darstellt und kein zugehöriges Symbol hat, wird diese Operation in C mit "<<" gekennzeichnet. Eine Linksshiftoperation wird genutzt, um eine Bitfolge in eine Bitmaske umzuwandeln. Um beispielsweise die Maske für das sechste Bit (Rang 5) zu erhalten, muss das erste Bit um fünf Stellen nach links verschoben werden. In C wird diese Operation wie folgt geschrieben: |
| |
| ~~CL~~ | ~~CL~~ |
| <code c> | <code c> |
| REG = 0x01 << 5; | REG = 0x01 << 5; |
| // Now REG = 0x20 | // Ergebnis REG = 0x20 |
| </code> | </code> |
| |
| [{{ :images:logic:op_bit_shift_right.png?241|Shift right}}] | [{{ :images:logic:op_bit_shift_right.png?241|Rechtsshift}}] |
| |
| Shift right operation works similarly to shift left operation. It is marked as ">>" in C. Right shift is used to get the logical value of a bit from a bitmask. A leading example showed how to read the value of a single bit. Let's suppose the bit to read is not of the lowest rank, but for example of rank 5. In this case, the result would be either 0x20 or 0x00, but sometimes a result of 1 or 0 is needed and that is when the right shift comes to the rescue. The example operation on the right looks like this in C: | Der Rechtsshift funktioniert auf die gleiche Weise und wird in C durch ">>" dargestellt. Rechtsshiftoperationen dienen dazu, den logischen Wert eines Bits aus der Bitmaske zu erhalten. An einem vorherigen Beispiel wurde bereits gezeigt, wie der Wert eines einzelnen Bits gelesen werden konnte. Ist dieses Bit nun nicht das niederwertigste, sondern zum Beispiel eines mit dem Rang 5, wäre das Ergebnis entweder 0x20 oder 0x00. Allerdings wird manchmal ein Ergebnis von 1 oder 0 benötigt und genau hier kommt die Rechtsshiftoperation zur Anwendung. Der Rechtsshift aus dem Beispiel rechts sieht in C folgendermaßen aus: |
| |
| ~~CL~~ | ~~CL~~ |
| |
| <code c> | <code c> |
| // Let's suppose REG = 0x20 | // Annahme REG = 0x20 |
| unsigned char x = REG >> 5; | unsigned char x = REG >> 5; |
| // Now x = 0x01 (or simply 1) | // Ergebnis x = 0x01 (or simply 1) |
| </code> | </code> |
| |
| If a bit is shifted right from the lowest rank or left from the highest rank by the bit shifting operation, it disappears. Some programming languages also have rotating bit shift operations, where the bit doesn't disappear, but moves from the lowest rank to the highest or vice versa. C doesn't have that kind of bit shift operations, but they can be written by the programmer if needed. | Wird durch diese Operationen ein Bit vom niedrigsten Rang nach rechts oder vom höchsten Rang nach links verschoben, verschwindet es. Einige Programmiersprachen verfügen jedoch über rotierende Bitshiftoperationen, bei denen ein Bit nicht verschwindet, sondern vom niedrigsten zum höchsten Rang wandert oder umgekehrt. In C gibt es diese Operationen nicht, sie können jedoch bei Bedarf vom Programmierer selbst geschrieben werden. |
| |
| All bit operations work with not only registers, but with variables and constants as well. The latter can of course only be used as operands and not the result. | Sämtliche Bitoperationen sind nicht nur mit Registern durchführbar, sondern auch mit Variablen und Konstanten. Letztere können jedoch ausschließlich als Operanden, nicht als Ergebnis genutzt werden. |
| |
| ===== AVR registers ===== | ===== AVR Register ===== |
| |
| To do anything actual with the microcontroller's registers, one needs to know how to use that particular microcontroller. Each microcontroller comes with one or several datasheets, which describe the whole structure and functionality or the microcontroller. The datasheet also describes the registers. The following will help understand the register descriptions in AVR datasheets. | Um tatsächlich mit dem Register eines Mikrocontrollers zu arbeiten, ist es notwendig zu wissen, wie dieser spezielle Mikrocontroller verwendet wird. Zu jedem Mikrocontroller gibt es ein oder mehrere Datenblätter, welche seine Struktur und Funktionalität beschreiben. Dieses Datenblatt enthält auch Informationen über die Register. Der folgende Abschnitt dient dazu, die Registerbeschreibungen der AVR Datenblätter zu verstehen. |
| |
| [{{ :images:logic:avr_example_register.png?580 |One of AVRs registers from its datasheet}}] | [{{ :images:logic:avr_example_register.png?580 |Eines der AVR Register, Datenblattansicht}}] |
| |
| The image shows ATmega128 microcontroller's UCSRnA register, which stands for "USART Control and Status Register A". This register is used to configure AVR's USART module and read its states. All AVR register names are written in capital letters, but as the reader might notice, the register name contains also a lower case n. A lower n is used to mark some module's index. Since ATmega128 has 2 almost identical USART modules, they are not described twice, but only once and the n must be read as 0 or 1 by the user. Therefore ATmega128 has registers UCSR0A and UCSR1A. | Die Abbildung zeigt das UCSRnA Register des ATmega128. UCSRnA bezeichnet „USART Control and Status Register A“. Dieses Register wird verwendet um das USART Modul der AVR Mikrocontroller zu konfigurieren und deren Status auszulesen. Sämtliche AVR Registernamen werden in Großbuchstaben geschrieben, jedoch enthält der Name auch ein kleines n, welches den Index des Moduls kennzeichnet. Der ATmega128 verfügt über zwei nahezu identische USCART Module, die jedoch nicht getrennt beschrieben werden, sodass der Nutzer das n als 0 oder 1 lesen muss. Aus diesem Grund hat der ATmega128 die Register USCR0A und UCSR1A. |
| |
| The content of the register is marked by an 8-slot box with a bold line around it. Each slot marks one bit. Bit ranks are marked above the box - increasing from right to left. Since AVR is an 8-bit microcontroller, most of the registers are 8-bit as well. There are some exceptions, a few registers are 16-bit, but they actually consist of two 8-bit registers. Like each register has a name, each bit in the register has also a name - just like the buttons on a tape player. Each bit is described in the datasheet. Bit names are abbreviations as well and the lower n must be substituted with the module's index, just like with register names. Some registers don't use all 8 bits, in this case the bit's slot is marked with a hyphen. | Der Inhalt des Registers wird durch eine Box mit 8 Feldern und einem dicken schwarzen Rahmen dargestellt. Jedes Feld steht hier für ein Bit. Die Bitränge sind oberhalb der Box abgebildet – von links nach rechts ansteigend. Da der AVR ein 8-Bit Mikrocontroller ist, haben auch die meisten seiner Register 8-Bit. Es gibt auch Ausnahmen, so sind einige Register 16-Bit groß, aber tatsächlich bestehen sie aus zwei 8-Bit Registern. So wie jedes Register einen Namen hat, hat auch jedes Bit innerhalb des Registers einen Namen – so wie die Tasten an einem Kassettenrekorder. Jedes Bit wird im Datenblatt beschrieben. Wie Registernamen sind Bitnamen ebenfalls Abkürzungen und das kleine n entspricht jeweils dem Modulindex. Einige Register nutzen weniger als 8 Bit, in diesem Fall ist das Feld eines solchen Bits mit einem Trennstrich markiert. |
| |
| Below the register's bits are two lines, which state whether the bit is readable (R), writable (W) or both (R/W). For example, the status bits can't be overwritten and even if it's attempted in the program, the bit will remain unchanged. If the bit is marked as writable, reading it will always result in one specific value stated in the datasheet. The second line specifies the default value of the bit, which it has after the reset of the microcontroller. | Unterhalb der Bits des Registers finden sich im Datenblatt zwei Zeilen. Die erste gibt an, ob das Bit lesbar (R), beschreibbar (W) oder beides (R/W) ist. Kann beispielsweise der Status eines Bits nicht überschrieben werden, so bleibt das Bit unverändert, auch wenn das mit dem Programm versucht wurde. Durch Auslesen eines beschreibbaren Bits wird stets ein spezifischer Wert ausgegeben, der im Datenblatt angegeben ist. In der zweiten Zeile wird der Standardwert dargestellt, den das Bit nach dem Reset des Mikrocontrollers hat. |
| |
| While AVR register names point to an actual memory slot address, the bit names hold the rank number of the corresponding bit. Therefore it is necessary to transform the names to bitmasks using a shift operation, in order to manipulate with bits in a register. The following code contains a few example lines for using the USART 0 module's register. | Während die AVR Registernamen auf eine tatsächliche Adresse im Speicher verweist, enthalten Bitnamen den Rang und das zugehörige 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. |
| |
| <code c> | <code c> |
| // Set TXC0 bit high | // Setze TXC0 Bit high |
| UCSR0A |= (1 << TXC0); | UCSR0A |= (1 << TXC0); |
| |
| // Set U2X0 bit low | // Setze U2X0 Bit low |
| UCSR0A &= ~(1 << U2X0); | UCSR0A &= ~(1 << U2X0); |
| |
| // Read the value of UDRE0 bit(mask) | // Lies den Wert aus UDRE0 Bit(Maske) |
| unsigned char u = (UCSR0A & (1 << UDRE0)); | unsigned char u = (UCSR0A & (1 << UDRE0)); |
| |
| // At this point u value is either 0 or 32, | // An dieser Stelle ist der Wert entweder 0 oder 32, |
| // which enables using it in a logical operation | // wodurch die Nutzung in einer logischen Operation aktiviert wird |
| if (u) | if (u) |
| { | { |
| // Invert MPCM0 bit | // Invertiere MPCM0 Bit |
| UCSR0A ^= (1 << MPCM0); | UCSR0A ^= (1 << MPCM0); |
| } | } |
| |
| // Sometimes it is necessary to acquire a specific 0 or 1 value, | // Manchmal ist es notwendig einen spezifischen 1 oder 0 Wert zu erhalten |
| // so the read bit needs to be shifted right | // Dazu muss das Bit nach rechts verschoben werden |
| u >>= UDRE0; | u >>= UDRE0; |
| |
| // Now the value of u is either 0 or 1 | // Nun ist der Wert entweder 0 oder 1 |
| </code> | </code> |
| |