Mikrocontroller – Ein Leitfaden für Anfänger – Überarbeitung des ersten Programms, um die LED zum Blinken zu bringen und eine Einführung in bitweise Operationen

Mikrocontroller - Ein Anfängerleitfaden - Überarbeitung des ersten Programms, um die LED zum Blinken zu bringen und eine Einführung in Bitoperationen

Du hast das erste Programm geschrieben, welches eine LED einschaltete. Ja, das war spektakulär! Nun, nicht wirklich, aber lass uns ein bisschen Verrücktheit in die LED bringen. Wir geben ihr eine "bipolare" Persönlichkeit, indem wir sie blinken lassen. Dann erhöhen wir die Schlagzahl und lassen sie wirklich schnell blinken. Das Programm ist überraschend prägnant und einfach zu implementieren.

Sieh selbst:

#include
#include

int main(void)
{
DDRB |= 1 << PINB0;
while (1)
{
PORTB ^= 1 << PINB0;
_delay_ms(100);
}
}

HEY!! Was sind das für verrückte Symbole!! Verrückt scheint hier ein häufiges Thema zu sein. Nun, ich werde es erklären. Aber, ich verspreche, es ist ziemlich einfach. Du musst dir nur ein paar Dinge merken. Ich werde ein wenig ins Detail gehen, aber wenn du es nicht verstehst, mach dir keine Sorgen, merke dir einfach, was die gesamte Anweisung bewirkt, und es wird dir gut gehen. Ich werde dir einen Hinweis auf dem Weg geben. Hier kommt die Erklärung der Bitoperationen:

Es gibt logische Operatoren namens AND, OR, NOT und XOR, mit denen wir uns zu diesem Zeitpunkt beschäftigen. Sie bedeuten wirklich das, was sie sagen. Dies alles dient dazu, zwei Bits zu vergleichen, "1" und "0". Siehst du? Wie kann es schwierig sein, nur zwei Zahlen zu vergleichen! "1" AND "1" ist Wahr oder "1". Und ja, du hast es erraten, "0" AND "0" ist Falsch oder "0". Aber was ist "0" AND "1" und umgekehrt? Nun, Falsch oder "0", offensichtlich. Diese sind unterschiedlich, also sind sie wahrhaftig falsch.

Beispiel AND Binärzahloperation ("&" wird in der C-Programmierung für AND verwendet):

01001011 &
10001101
gleich
00001001

Einfach, oder? Nun, OR ist noch einfacher! "1" OR "1" ist "1", offensichtlich. "0" OR "0" ist auch "0". Es fängt an, sehr ähnlich wie AND auszusehen, aber hier ist der Unterschied. Wenn die beiden Zahlen unterschiedlich sind, führt dies zu "1". Also, "1" OR "0" ist "1".

Verwenden wir die gleiche Binärzahl für das Beispiel (dieses lustige Zeichen "|" ist das OR, manchmal über dem "\" auf der Tastatur):

01001011 |
10001101
gleich
11001111

Hmm, das schaltete alle Stellen ein, wo Einsen fehlten! Hier geschieht die Magie. Ja, es behielt die Einsen in der ersten Zahl und wo Einsen in der zweiten Binärzahl, aber nicht der ersten, sind, änderte es diese zu Einsen. Sehr einfach. NOT nimmt einfach alle Bits und dreht sie um. Zum Beispiel, für diese Binärzahl: 01001101 wird zu 10110010. Es verwandelte die 0en in 1en und die 1en in 0en, aber verwechsle dies nicht mit dem XOR.

XOR ist ähnlich wie OR, aber "1" XOR "1" ist tatsächlich "0". Ich werde einfach das Beispiel zeigen und du kannst herausfinden, was passiert.

01001011 ^
10001101
gleich
11000110

Ja, du hast es erraten, das "^" über der "6" ist das XOR-Symbol. Hmmm... Das "|" und das "^" sind im Programm. Cool. Nun, da wir Programm denken, lassen Sie uns das Zeug zerlegen, das wir noch nicht kennen!

#include

Du weißt bereits, was das tut, also werde ich deine Zeit nicht damit verschwenden, aber es gibt eine neue #include-Anweisung. Die delay.h wird uns ein paar praktische Methoden zur Verfügung stellen, die wir nutzen können. Genau wie der Name schon sagt, wird delay.h uns eine Möglichkeit bieten, Verzögerungen in unserem Programm zu erzeugen.

Den "main"-Teil überspringend, da wir ihn bereits kennen, sehen wir, dass der DDRB geändert wurde. Hab keine Angst! Hier ist der Prozess, von wo wir waren bis wo wir sind:

Das hatten wir vorher. Dies ist keine sehr gute Methode, um die Pins zu manipulieren, da wir einfach alle Pins von 1 bis 7 als Eingabe geändert haben, aber "was wäre, wenn" wir ein größeres Programm hätten, das diese Pins für andere Dinge verwendete, wie zum Beispiel Pin 2, der den Bremsdruck für das Antiblockiersystem regelt. Man würde ihn nicht einfach willkürlich als Eingabe festlegen wollen. Das würde die Bremsen nutzlos machen (was WIRKLICH schlimm wäre).

DDRB = 0b00000001;

Wir brauchen eine Möglichkeit, NUR ein Bit zu beeinflussen, das Pin 0 Bit. Nun, wenn du oben auf "OR" schaust, können wir dies mit einer Maske tun (nicht die Karnevalsmaske, an die du denkst, sondern eine Binärmaske).

DDRB = DDRB | 0b00000001;

Dies nimmt seinen früheren Wert und verknüpft ihn mit einer Maske. Die Maske ist: 0b00000001. Ja, dies sieht aus wie die tatsächliche Binärzahl, aber wenn der vorherige DDRB beispielsweise 0b01001010 war, dann würde eine OR-Verknüpfung damit mit unserer Maske so aussehen: 0b01001010 | 0b00000001 = 0b01001011. Was ist im Ergebnis anders? Richtig, nur das Pin 0 Bit wird geändert!

Diese Anweisung kann in C++ weiter komprimiert werden:

DDRB |= 0b00000001;

Aber das steht nicht im Programm. Obwohl das völlig gültig ist, warum nutzen wir nicht einige der Definitionen in der io.h Header-Datei? Ich meine, es ist ja für unsere Bequemlichkeit da, nicht wahr? Beachte meine Verwendung von Kontraktionen! Das ist dasselbe in C++: "it's" ist wirklich "it is", genau wie "DDRB |= 0b00000001" dasselbe ist wie "DDRB = DDRB | 0b00000001". Ich versinke in meinem Stuhl mit dieser schlechten Analogie. Was auch immer, hilft!

Warum also "DDRB |= 1 << PINB0"?

1 << PINB0 ist der Vorgang der Maskenerstellung. Die "1" stellt dar, was in die Maske eingefügt wird, das << ist ein Links-Shift-Operator. Er tut GENAU das, was er sagt, und PINB0 ist eine Anzahl von Positionen, um die die "1" nach links verschoben wird. Im Wesentlichen ist PINB0 nur gleich 0. Du beginnst also mit einem 0b00000000, und du fügst eine "1" hinzu, um 0b00000001 zu erhalten, und dann verschiebst du es um 0 Positionen nach links. Du bleibst also bei 0b00000001, der gleichen Zahl wie oben. Was wäre also, wenn es PINB4 wäre? Die Anweisung wäre: 1 << PINB4. Die "1" würde 4 Mal nach links verschoben, was zu: 0b00010000 führt. Denke daran, wir verwenden einen Nullindex, es gibt also vier 0en nach der 1.

Gehen wir zur While-Schleife über. Du hast Recht, wir hatten vorher nichts in der "unendlichen Schleife". Nun, jetzt müssen wir dem Mikrocontroller etwas Aktion zeigen. Dies ist nur innerhalb der Schleife möglich. Die Schleife ist der Ort, an dem die Aktion immer wieder wiederholt wird. Wenn die Aktion vor der Schleife stünde, würde die Aktion nur einmal geschehen, wie das Festlegen der Pinrichtung, was für dieses Programm angemessen ist. Aber um ein ewiges Blinken zu erzeugen, müssen wir PINB0 innerhalb der Schleife ein- und ausschalten. Hier kommen auch die Verzögerungen ins Spiel. Wenn wir keine Verzögerungen hätten, würden wir die LED überhaupt nicht blinken sehen, es würde aussehen, als wäre sie nur an, da das Blinken schneller geschehen würde, als das Auge wahrnehmen könnte, also müssen wir es verlangsamen.

Wir wissen, wie man ein bestimmtes Bit in der Binärzahl setzt, aber wir wissen noch nicht, wie man ein bestimmtes Bit auf "0" setzt, wenn es eine "1" ist. Der folgende Code macht genau das, aber du wirst bemerken, dass es nicht das ist, was das Programm zeigt. Die ersten beiden Zeilen setzen das Bit auf "1" (5 Volt, Licht) und pausieren für 100 Millisekunden (übrigens, man kann Mikrosekunden verwenden, indem man "ms" in "us" ändert). Die zweiten beiden Zeilen setzen das PINB0-Bit auf "0" (0 Volt, kein Licht). Nein, der AND-Vergleich kann nicht einfach eine "0" aus dem Bit machen, aber wenn man die binäre Maske NICHT "~", dann werden alle 0en zu 1en und alle 1en zu 0en. Dies ermöglicht es dir, nur das PINB0-Bit zu beeinflussen und es in eine "0" zu verwandeln. Ich habe die Klammern hinzugefügt, nur um die Maskierungsoperation einzuschließen, damit das NOT die gesamte Maske und nicht nur die "1" vor dem Links-Shift "<<" negieren kann.

PORTB |= 1 << PINB0;
_delay_ms(100);
PORTB &= ~(1 << PINB0);
_delay_ms(100);

Wenn die Verzögerung für Ein und Aus gleich sein soll, könnten wir die vorherigen vier Zeilen auf nur zwei verkürzen und die XOR-Operation nutzen. Denke daran, das XOR wird unseren spezifischen Pin auf 1 setzen, wenn er 0 ist, und umgekehrt. Diese Anweisung wird nur das PINB0 beeinflussen. Jedes Mal, wenn die Anweisung ausgeführt wird, wird sie das Bit umkehren.

PORTB ^= 1 << PINB0;
_delay_ms(100);

Das war's. Sieh, das war überhaupt nicht schmerzhaft.

Zurück zum Blog

Hinterlasse einen Kommentar

Bitte beachte, dass Kommentare vor der Veröffentlichung freigegeben werden müssen.