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?
verunden? PORTA &= PORTA & 11111110
Terry schrieb: > Wie setzt man das am besten in der Praxis um? PORTA = PORTA & 0b11110000 | 0b00001110;
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?
Oder so:
1 | struct nibbles |
2 | {
|
3 | uint8_t low_nibble:4, high_nibble:4; |
4 | } __attribute__((__packed__)); |
5 | |
6 | #define HIGH_NIBBLE(byte) ((*(volatile struct nibbles*)&byte).high_nibble)
|
7 | #define LOW_NIBBLE(byte) ((*(volatile struct nibbles*)&byte).low_nibble)
|
8 | |
9 | |
10 | // Usage
|
11 | HIGH_NIBBLE(PORTB) = 5; |
12 | LOW_NIBBLE(PORTB) = 0x08; |
:
Bearbeitet durch User
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. ;-)
:
Bearbeitet durch User
"0b" eröffnet eine als Byte zu interpretierende Folge von 8 Bits (MSB first). Wer "0b1110" schreibt, ist für mich DOOF.
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
A. K. schrieb: >> Wer "0b1110" schreibt, ist für mich DOOF. > > 0b1110 ist 0x000E, nicht 0xD00F. Der frühe Vogel fängt den Wurm ;-)
A. K. schrieb: > Oder man nimmt auf nicht zu alten AVRs > PINA = (PORTA & 0x0F) ^ 0b1110; Schaltet PINA nicht lediglich die Pullups auf Port A???
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: >> PINA = (PORTA & 0x0F) ^ 0b1110000; Müsste es dann nicht eher heißen: PORTA = (PINA & 0x0F) ^ 0b1110000;
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.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.