Hallo,
ich möchte bei einem AVR-Port das untere und das oberes Nibble
unabhängig voneinander beschreiben.
Sagen wir mal, im Portregister stünde
a = 0b11101010;
PORTA = a;
Jetzt soll das untere Nibble verändert werden von 1010 zu 1110. Das
obere Nibble soll aber erst mal erhalten bleiben.
Wie setzt man das am besten in der Praxis um?
Danke für die schnellen Antworten!
Also in zwei Schritten:
PORTA = PORTA & 0b11110000; //unteres Nibble löschen
PORTA = PORTA | 0b00001110; //unteres Nibble neu beschreiben
Richtig?
Terry schrieb:
> Also in zwei Schritten:> PORTA = PORTA & 0b11110000; //unteres Nibble löschen> PORTA = PORTA | 0b00001110; //unteres Nibble neu beschreiben
Funktioniert zwar, zu beachten ist aber, daß im unteren Nibble evtl.
auch Bits gesetzt sein könnten, die gesetzt bleiben sollen. Im o.g. Code
tritt bei solchen Bits durch das kurzzeitige Löschen ein Flackern des
Signals an den Portpins auf. Das ist egal, wenn nur LEDs angeschlossen
sind, da man das Flackern bei hoher µC-Taktrate nicht sehen kann. Wenn
aber kritische Geräte angeschlossen sind, dann ist es nicht egal, ob das
Signal flackert oder konstant ist. Dann besser so:
1. Port in Variable (Register) einlesen.
2. Bits in der Variablen manipulieren.
3. Variablenwert in den Port schreiben.
Rainer V. schrieb:> 1. Port in Variable (Register) einlesen.> 2. Bits in der Variablen manipulieren.> 3. Variablenwert in den Port schreiben.
Richtig. Und wenn man sich nicht sicher ist, ob irgendeine verschissene
ISR Ausgaben auf den gleichen Port tätigt, gehört natürlich ein
cli/sei-Rahmen um die Sache.
Bei richtigen Programmierern ist das natürlich kein Thema, die wissen,
ob da eine ISR reingrätschen könnte, aber bei C&P-"Programmierern"...
c-hater schrieb:> Richtig. Und wenn man sich nicht sicher ist, ob irgendeine verschissene> ISR Ausgaben auf den gleichen Port tätigt, gehört natürlich ein> cli/sei-Rahmen um die Sache.
Oder man nimmt auf nicht zu alten AVRs
PINA = (PORTA & 0x0F) ^ 0b1110;
Schützt gegenüber Veränderungen an den oberen Bits.
Die Übersetzung in Asm überlasse ich dir. ;-)
Und wer meint eine "binary constant" habe exakt 8 Bit zu haben, der kann
(zumindest Englische Doku des GCC) nicht lesen.
Das ist irgendwie auch doof ;-)
Es dürfen nämlich 1..64 (eventuell auch mehr) sein.
Kurt schrieb:> "0b" eröffnet eine als Byte zu interpretierende Folge von> 8 Bits (MSB first).
Das "b" kommt von Bit, nicht von Byte. Der Typ entwickelt sich grad wie
bei 0 oder 0x vorneweg, ist also "int".
https://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html> Wer "0b1110" schreibt, ist für mich DOOF.
0b1110 ist 0x000E, nicht 0xD00F.
Ein Nibble auf'm 8-Bit AVR Port kann nicht getrennt vom anderen Nibble
als Einheit beschrieben werden. Bitweise per ASM könnte man noch das
andere Nibble unangetastet lassen.
zappa schrieb:> Ein Nibble auf'm 8-Bit AVR Port kann nicht getrennt vom anderen Nibble> als Einheit beschrieben werden.
Elektrisch gesehen nicht, funktional schon. Jene AVRs, die beim
Schreiben auf PINx eine Toggle-Funktion ausführen, können einen
beliebigen Subset von Portbits geschlossen auf beliebige Werte setzen,
ohne die übrigen Pins zu beeinflussen oder von ihnen beeinflusst zu
werden.
Voraussetzung ist nur die Hoheit über die betroffenen Pins, d.h.
zwischen lesen von PORTx und schreiben von PINx dürfen sich die zu
modifierenden Pins nicht ändern. Die anderen hingegen schon.
Rolf schrieb:> Schaltet PINA nicht lediglich die Pullups auf Port A???
Nur wenn die Portpins als Eingang konfiguriert sind. Sonst toggelt eine
"1" im PIN Register den Ausgang (bei neueren AVR zB ATtiny25, ATMega88
... und fast alle anderen)
zappa schrieb:> Rolf schrieb:>> Schaltet PINA nicht lediglich die Pullups auf Port A???>> Nur wenn die Portpins als Eingang konfiguriert sind. Sonst toggelt eine> "1" im PIN Register den Ausgang (bei neueren AVR zB ATtiny25, ATMega88> ... und fast alle anderen)
Mist, reingefallen. Bei Eingang werden die Pullups mit dem Portregister
geschaltet! Im PIN werden die Zustaände abgefragt.
Rolf schrieb:> Rolf schrieb:>>> PINA = (PORTA & 0x0F) ^ 0b1110000;>>> Müsste es dann nicht eher heißen:>> PORTA = (PINA & 0x0F) ^ 0b1110000;
Welchen Zweck hat hier das XOR?
Die oberen 4 Bits des Bytes vom PINA sind auf jeden Fall 0. Die
Verundung mit 0x0F erzwingt dies. Von diesen 4 Bits mittels einem XOR 3
Bits auf 1 zu setzen kann man natürlich machen. Allerdings war die
Vorgabe, dass diese Bits unangetastet bleiben sollen, wenn man auf den
Port ausgibt.
Rolf schrieb:> Müsste es dann nicht eher heißen:> PORTA = (PINA & 0x0F) ^ 0b1110000;
Nein. Es geht in
PINA = (PORTA & 0x0F) ^ 0b1110;
um die implizite XOR-Funktion beim Schreiben auf PINA. Gibts noch nicht
im Mega8, aber im Mega88. Schreiben auf PINA wie in
PINA = <expr>;
entspricht bei diesen Devices
PORTA ^= <expr>;
wobei das aber im Port durchgeführt wird und nicht unterbrechbar ist. In
(PORTA & 0x0F) ^ 0b1110
sind nur jene Bits gesetzt, die geändert werden müssen um in den unteren
4 Bits auf den Zustand 0b1110 zu kommen.