Wie funktioniert zB PortB.B0 = 1; Befehl den Zustand eines bestimmten Pins in einem Mikrocontroller ändern.
Der Mikrocontroller hat normalerweise eine 8-Bit-Datenleitung, was bedeutet, dass er gleichzeitig vom gesamten Port schreibt und liest. Meine Frage ist, ist es die Aufgabe des Compilers, den gesamten Port zu lesen, das angegebene Bit zu setzen und das gesamte Byte zurück in den Port zu schreiben, oder kann der Mikrocontroller selbst ein einzelnes Bit ändern?
Ich nehme an, Sie sprechen von den PORT-Registern in den gängigen Hobby-PICs. Diese Chips haben Bit-Level-Set und klare Anweisungen, und es kann erwartet werden, dass ein Compiler übersetzt
PortB.B0 = 1;
Zu
BSF PORTB, 0
ABER ABER ABER ABER ABER ABER
Diese Bit-Setz- und Bit-Lösch-Befehle werden als ein vollständiger 8-Bit-Lese-Modifizier-Schreib-Zyklus ausgeführt. Die CPU liest den 8-Bit-Port, löscht das niedrigste Bit und schreibt das Ergebnis zurück. Dies wäre nur von akademischem Interesse, wenn nicht die Tatsache, dass das Lesen von PORTB die logischen Pegel auf Chip-Pins liest. (In den meisten anderen Architekturen würde es das PORTB-Ausgangsregister lesen.) Wenn der Pin so stark belastet ist, dass sein externer Pegel nicht den Pegel liest, auf dem der Eingangspuffer ihn korrekt erkennt, kann der zurückgelesene Wert von dem zuletzt geschriebenen Wert abweichen Es. Das ist das gefürchtete Read-Modify-Write-Problem. Die kanonische Lösung besteht darin, Ihre Bitoperationen an einem RAM-Speicherort (der als Schatten des Ports bezeichnet wird) auszuführen und dann den Schattenpuffer mit normalen 8-Bit-Operationen in den Port zu schreiben.
Wenn Sie diesen kanonischen Ansatz nicht verwenden, werden Sie in interessanten Zeiten leben: Das Setzen eines weiteren Pins in einem Ausgangsport kann beispielsweise die zuvor gesetzten Pins löschen. Und das natürlich nur in einer Produktionssituation, niemals auf Ihrem Testbed.
Nebenbemerkung: In der Jal-Sprache (die ich vor langer Zeit entworfen und implementiert habe und die jetzt von anderen gepflegt wird) gibt es etwas Sprach- und Bibliotheksmagie zu machen
pin_a_5 = true
bedeuten
port_a_shadow |= (1 << 5 )
port_a = port_a_shadow
Randbemerkung 2:
Moderne PICs haben ein LAT-Register für jeden Port. Das Lesen dieser Register ergibt den Wert, der zuletzt in sie geschrieben wurde, daher leiden sie nicht unter dem Read-Modify-Write-Problem. AFAIK Jal auf diesen Chips macht sich nicht die Mühe, ein Schattenregister zu verwenden.
Wenn Sie sich die Disassemblierung dieser Codezeile ansehen, wird sie höchstwahrscheinlich zu bsf LATB,0
. Das ist die Bit-Set-Anweisung. Wie Compiler mit dieser Art von Szenario umgehen, hängt von der Prozessorarchitektur ab. Jeder Compiler und Befehlssatz ist anders.
Andi aka
Adam Lawrence
Kenny