Ich gebe eine 6-Bit-Zahl auf PORTA (RA0-RA5) aus, wie schreibe ich in diese Bits, ohne zu verfälschen, was bereits auf RA6 und RA7 ist?
Zum Beispiel, wenn ich 0x3F auf den Bits RA0-RA5 ausgeben möchte. Wenn ich das verwende PORTA = 0x3F;
, wird 00111111 ausgegeben, wodurch effektiv gelöscht wird, was bereits in die Bits RA6 und RA7 geschrieben wurde.
Ich codiere in C mit MikroC auf einem PIC18
Eine Prozedur namens "Lesen-Ändern-Schreiben".
Was es damit auf sich hat, steckt schon im Namen. Du liest. Dann änderst du. Dann schreibst du.
Lesen:
//Read in the value of the output register
tempVariable = [output register]
Ändern:
//set all bits you want to modify to be 0.
tempVariable &= [some mask];
//or in the values of the bits with those bits you want unchanged set to 0
tempVariable |= [new value of bits];
Schreiben:
//Write the new value back to the output register
[output register] = tempVariable;
Der Schlüssel liegt im Wesentlichen darin, die Werte der Bits, die Sie unverändert lassen möchten, zusammen mit den neuen Werten der Bits, die Sie ändern möchten, in das Ausgangsregister zurückzuschreiben.
Um festzustellen, was das Ausgangsregister für Ihr Gerät ist, sollten Sie sich auf dessen Datenblatt beziehen.
Wir können nicht einfach direkt in das Register schreiben, da dies auch die Bits betrifft, die wir nicht ändern möchten. Wir brauchen also eine Abfolge von Operationen, die nur die Bits ändern, die wir wollen. Hier kommen bitweise Operatoren ins Spiel.
Es gibt mehrere bitweise Operatoren, aber die beiden wichtigen sind &
(und) und |
(oder). Bitweise und alles mit einer 0 und es setzt dieses Bit auf 0, bitweise und alles mit 1 und es bleibt gleich. Bitweise oder irgendetwas mit einer 1 und es setzt dieses Bit auf eine 1, bitweise oder irgendetwas mit 0 und es bleibt gleich. Diese beiden Operatoren ermöglichen es uns, die erforderlichen Änderungen vorzunehmen, da wir jetzt eine Möglichkeit haben, nur einige Bits auf 0 zu setzen, und eine Möglichkeit, nur einige Bits auf 1 zu setzen.
Der neue Wert, den Sie schreiben möchten, erfordert, dass einige Bits auf 0 und einige Bits auf 1 gesetzt werden. Wir können dies erreichen, indem wir bitweise und gefolgt von einem bitweisen or ausführen . Das und wird verwendet, um alle Bits, die wir ändern möchten, auf 0 zu setzen, damit wir dann das oder ausführen können, das nur die Bits, die wir auf 1 haben möchten, auf 1 setzt.
Ein Beispiel hilft. Angenommen, Sie möchten die unteren 5 Bits auf einen Wert von ändern 0b01011
, die oberen 3 Bits jedoch unverändert lassen. Nehmen wir auch an, der aktuelle Wert ist 0b10111101
. Also folgen wir dem Ablauf:
Schritt 1, Maske:
Current: 0b101 11101
Bitmask: 0b111 00000 <- remember a 1 means don't change, a 0 means clear.
Result : 0b101 00000
Schritt 2, ändern:
Masked : 0b101 00000
New Val: 0b000 01011 <- remember a 1 means set to 1, a 0 means unchanged
Result : 0b101 01011
Und da haben Sie es - beachten Sie, dass die oberen 3 Bits in beiden Operationen unverändert blieben, während die unteren Bits aktualisiert wurden, um dem neuen Wert zu entsprechen.
Um einen in den Kommentaren und der anderen Antwort erwähnten Punkt anzusprechen, sollte dies tatsächlich im Ausgangsregister erfolgen, was die ursprüngliche Absicht meiner Antwort war. Es scheint einige Verwirrung zu geben, wenn ich annehme, dass ich mich mit Port auf die PORTx-Register in PICs beziehe - tatsächlich ist das Ausgangsregister auf einigen Geräten das LATx-Register. Einige PICs haben kein LATx-Register. Bei AVRs ist zum Beispiel PORTx das Ausgangsregister. Das Datenblatt für Ihr Gerät sagt Ihnen, was das Ausgangsregister ist.
Darüber hinaus kann die Technik verwendet werden, um sowohl Variablen als auch Register zu ändern, und kann verwendet werden, wenn die Register für andere Dinge als nur E / A-Ports geändert werden - Sie können auch Dinge wie Steuerregister für serielle Peripheriegeräte und dergleichen ändern.
Aufgrund der Unterschiede in der Benennung von Registern und der Tatsache, dass der Prozess ein sehr universeller Ansatz ist, hatte ich oben versucht, allgemein zu sein, da das Gleiche nicht nur für PICs, sondern für jeden Mikrocontroller gilt - eigentlich für so ziemlich alles, was einige erfordert Bits eines Registers modifiziert werden, aber nicht andere.
Im Allgemeinen sollten Sie in der PIC18-Architektur niemals Read-Modify-Write-Befehle wie verwenden
PORTA |= 0x3F; // Bits 0 bis 5 setzen
Verwenden Sie lieber
LATA |= 0x3F; // Bits 0 bis 5 setzen
oder
LATA &= ~0x80; // Bit 7 löschen
Der Grund dafür ist, dass die Anweisung PORTA |= xx zuerst die Bitpegel an den Pins liest, sie modifiziert und dann das Ergebnis in den Port-Latch schreibt.
Der LATA-Befehl liest die Bits im Port-Latch, modifiziert sie und schreibt dann das Ergebnis in den Port-Latch.
Wenn die Port-Pins aus irgendeinem Grund (z. B. Lade- oder Ausbreitungsverzögerungen) nicht auf den richtigen und gültigen Logikpegeln liegen, kann der Lese-Modifizier-Schreib-Befehl versehentlich Bits modifizieren, die Sie nicht modifizieren wollten. Wenn Sie Pins von Eingang zu Ausgang tauschen, um Open-Drain-Pins zu simulieren, tritt ein ähnliches Problem für Pins auf, die vorübergehend Eingänge sind - der Ausgangslatch eines anderen Pins als der, den Sie absichtlich ändern, und dann, wenn Sie das TRIS-Register zurückschalten 0, um den simulierten offenen Drain einzuschalten, wurde der Latch-Zustand für dieses Bit geändert.
Wenn Sie für ältere PICs ohne LATx RMW verwenden müssen, können Sie ein Schattenregister manuell pflegen, es ändern und das Ergebnis dann in das Portregister übertragen.
Ein bisschen mehr Details zu dem, was ich oben geschrieben habe, von Ihrem Compiler-Lieferanten hier .
Manipuliert nur das niederwertigste Bit (LSB) eines Registers
Satz
GPIO_DATA = GPIO_DATA | 0x01;
Klar
GPIO_DATA = GPIO_DATA & (~0x01);
Unten ist eine Reihe von Notizen, die ich griffbereit habe und die von Nutzen sein könnten. Achten Sie auf die Hinweise in Rot.
Für eine detaillierte Erklärung schlage ich vor, dass Sie hier nachsehen .
Verweise:
uint128_t
&=
,|=
,^=
sind alles Operatoren, mit denen Sie in der eingebetteten Entwicklung sehr vertraut sein sollten.Tom Tischler
user_1818839