Warum kann ich beim XMega nur vernünftig auf die Portregister zugreifen,
wenn ich die OUTSET, OUTCLR, OUTTGL sowie DIRSET und DIRCLR direkt
beschreibe, so hier:
1
PORTC.OUTCLR=PIN3_bm;
und nicht über :
1
PORTC.OUTCLR|=(1<<PIN3_bp);
? Wenn ich letzteres mache überschriebt er irgendwie vorhandene
Konfigurationen anderer Pins, auch im Simulator. In der Errata steht
dazu nichts bzw. hab ich was übersehen?
Probiert's mal aus. Ich nutze das aktuelle AtmelStudio 6 (nicht die 6.1
Beta).
Ingo
Frage dazu: Warum sollte man das überhaupt machen wollen? Der Sinn von
OUTSET, OUTCLR, OTTGL etc ist es doch gerade, dieses ReadModifyWrite zu
vermeiden.
Detlev T. schrieb:> Frage dazu: Warum sollte man das überhaupt machen wollen? Der Sinn von> OUTSET, OUTCLR, OTTGL etc ist es doch gerade, dieses ReadModifyWrite zu> vermeiden.
Klar, abfinden kann ich mich damit ja. Auch ist mir den Sinn völlig
klar. Mich würde halt nur interessieren warum es nicht mit dem ODER
-oder UND-Zugriff klappt.
Ingo
Die Register OUTSET, OUTCLR und OUTTGL sind dafür gedacht, dass man
einzelne Bits bequem Setzen, Löschen oder Togglen kann, indem man eine 1
an die Stelle schreibt. Sie sind nicht dazu da, gelesen zu werden. Das
"normale Register" heißt nur OUT. Analog bei DIR.
Diese Anweisungen machen also das gleiche (nur dass die erste jeweils
schneller ist):
1
PORTC.OUTSET=PIN3_bm;
2
PORTC.OUT|=PIN3_bm;
Ebenso:
1
PORTC.OUTCLR=PIN3_bm;
2
PORTC.OUT&=~PIN3_bm;
Und:
1
PORTC.OUTTGL=PIN3_bm;
2
PORTC.OUT^=PIN3_bm;
Außerdem ist es egal, ob Du schreibst
1
PORTC.OUTSET=PIN3_bm;
oder
1
PORTC.OUTSET=(1<<PIN3_bp);
_bp steht für Bitposition, _bm für Bitmaske. In der Bitmaske ist das
Shiften mit (1 << x) schon mit enthalten.
ja, schon, nur haben die Atmel-Entwickler diese Möglichkeit wohl
trotzdem offen gelassen. Ich verwende auch nur OUTSET, OUTCLR und
OUTTGL. Read-modify-write war bei mir bisher auch nicht notwendig. Ist
aber trotzdem noch möglich.
Ingo schrieb:> Mich würde halt nur interessieren warum es nicht mit dem ODER> -oder UND-Zugriff klappt.
Was ergibt denn überhaupt ein Lesezugriff auf OUTCLR? Vermutlich nicht
den Wert von OUT. Und selbst wenn: Bei deinem Beispiel wird dann bei den
anderen Bits jede 1 zur Null. Natürlich ändert das den Wert!
XMega user schrieb:> Read-modify-write war bei mir bisher auch nicht notwendig
Es klappt auch mit diesen "Spezialregistern" nicht!
Miese Falle wenn man das von den normalen Megas gewohnt ist, zumal im DB
nichts dazu steht das es nicht geht, da steht sogar drinn das diese
Register auch gelesen werden können.
Ingo
> PORTC.OUTCLR |= (1<<PIN3_bp);
ist die verkürzte Form von :
PORTC.OUTCLR = PORTC.OUTCLR | (1<<PIN3_bp);
Kann das Register PORTC.OUTCLR denn gelesen werden und wenn ja werden
dann immer alle bits als 1er zurückgelesen oder als 0er oder eventuell
als undefiniert ?
Hab jetzt das Datenblatt nicht gelesen aber was steht denn da drinn über
dieses Register ?
Ingo schrieb:> Mich würde halt nur interessieren warum es nicht mit dem ODER> -oder UND-Zugriff klappt.
Dazu musst Du ins Datenblatt schauen. Da steht bei OUTSET, OUTCLR und
OUTTGL:
Reading this register will return the value of the OUT register.
Wenn Du also schreibst
1
PORTC.OUTCLR|=(1<<PIN3_bp);
ist das gleichbedeutend mit:
1
PORTC.OUTCLR=PORTC.OUT|(1<<PIN3_bp);
Es werden also alle aktuell auf 1 gesetzten Pins sowie PIN3 auf 0
gesetzt. Also letztlich alle Pins. Dann kannst Du auch gleich schreiben:
Fabian O. schrieb:> PORTC.OUTCLR = PORTC.OUT | (1<<PIN3_bp);
Aua! Das ist der entscheidende Hinweis, darüber habe ich garnicht
nachgedacht! Vielen Dank, das bring Licht ins Dunkle!
Wo wir gerade dabei sind, hat jemand ne Routine, am Besten in C, wie man
den WDT wieder aus kriegt (XMega)?
Ingo
Ingo schrieb:> Wo wir gerade dabei sind, hat jemand ne Routine, am Besten in C, wie man> den WDT wieder aus kriegt (XMega)?
Dazu musst Du die "Configuration Change Protection" aufheben. Das geht
in C nur, wenn der Compiler den Code richtig optimiert, damit es
innerhalb der vorgeschriebenen Taktzyklen klappt. Deshalb ist es
sauberer, das als Inline-Assembler zu machen:
> static inline void write_ccp_io(volatile uint8_t* addr, uint8_t value)> {> asm volatile (> "st %a0, %1; \n\t" // Unlock access by writing signature to CCP> "st %a2, %3; \n\t" // Write value to addr> : // No output operands> : "e" (&CCP), "r" (CCP_IOREG_gc), "e" (addr), "r" (value)> : "memory"> );> }>> void watchdog_disable(void)> {> write_ccp_io(&WDT.CTRL, (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm);> }
Ich habe den Code implementiert (ATxmega64A3) , aber der Watchdog lässt
sich dadurch leider nicht deaktivieren. Die in den Fuses ist WDLOCK
nicht gesetzt und das reseten des Watchdogs funktioniert einwandfrei.
Hat denn jemand eine Idee, wie die Deaktivierung bei diesem uC
funktionieren könnte ?