Hallo! Zur Zeit beschäftige ich mich mit MPLABX und dem XC8 Compiler. Bislang hatte ich nur mit Atmel zu tun. Wie kann ich Register mit dem XC8 wie bei Atmel beschreiben? Beispiel Atmel: REGISTER = (1<<XYZ)|(3<<ABC); //alle Bits in einem Rutsch geschrieben XYZ und ABC werden vom AVR Studio erkannt und somit funktioniert das ganze recht easy mit einem Schreibbefehl. Beispiel XC8: REGISTER = (1<<7)|(3<<2); //funktioniert, ist aber etwas unleserlich, da anonym REGISTERbits.XYZ = 1; //funktioniert auch, aber somit immer nur teilweise REGISTER = (1<<XYZ); //funktioniert nicht! aus dem XC8 Handbuch konnte ich auch keine passenden Infos ziehen. Also, wie kann ich auf die einzelnen "Bits" zugreifen ohne sie zu anonymisieren?
Irgendwo müssten das Macro "XYZ" definiert sein. Dazu könntest du einfach sämtlich .h-Dateien deines Compilers durchforsten.
ja, natürlich sind diese definiert... ich bekomme ja auch Zugriff auf diese Bits, aber immer nur indem ich das Register mit "bits" teilweise öffne. REGISTERbits.XYZ = ... Damit kann ich aber immer nur auf eine Stelle schreiben. REGISTER = (1<<REGISTERbits.XYZ); //funktioniert auch nicht oder bastelt der compiler aufeinanderfolgende Schreibbefehle zu einem zusammen? Quasi: REGISTERbits.XYZ = 1; | REGISTERbits.ABC = 3; |___ wird zu einem Schreibbefehl verwurstet?
@ DMDDE (Gast) >ja, natürlich sind diese definiert... ich bekomme ja auch Zugriff auf >diese Bits, aber immer nur indem ich das Register mit "bits" teilweise >öffne. >REGISTERbits.XYZ = ... Logisch. Weil man sich bei den Leuten vom XC8 Compiler für dieses Konzept entscheiden hat. Bei avr gcc hat man sich, warum auch immer, für ein anderes Konzept entschieden. >Damit kann ich aber immer nur auf eine Stelle schreiben. >REGISTER = (1<<REGISTERbits.XYZ); //funktioniert auch nicht Logisch. >oder bastelt der compiler aufeinanderfolgende Schreibbefehle zu einem >zusammen? Nein. >REGISTERbits.XYZ = 1; | >REGISTERbits.ABC = 3; |___ wird zu einem Schreibbefehl >verwurstet? Nein, das darf/kann er nicht, weil die Register volatile sind. Das MUSS er 1:1 umsetzen, ohne Umformung und Zusammenfassung. Eigentlich ist der Ansatz mit den einzelnen Registerbists besser, denn damit kann man nicht aus Versehen Bits in einem Register schreiben, die gar nicht existieren. Der avr gcc Ansatz ist deutlich fehleranfälliger, denn der Compiler kann nicht prüfen, ob die Bits in dem Register wirklich exisitieren. PORTA = (1<<PC5); ist eigentlich Unsinn, denn das Bit PC5 gibt es dort nicht. Durch "Zufall" ist PC5 == PA5 Wirklich problematisch sit es eher bei Steuerregistern, z.B. beim Timer TCCR0A = (1<<WGM03); ist totaler Unsinn, denn das Bit liegt in TCCR0B. Darüber sind schon viele Leute gestolpert. Und der Compiler kann keinerlei Fehlermeldung erzeugen. Schau mal ob in deinen Registerdefinitionen auch die Registetr als Gesamtkonstrukt vorhanden sind, etw so. REGISTERbits.all Dann könnte man wieder die gute, alte Atmel-Schiene fahren ;-) Aber dann musst du dir auch die gesamten Headerfiles mit allen Definitionen irgendwie erzeugen. Viel Spaß. Als Alternative, falls es dir um Speicherlatz und Geschwindigkeit geht, kann man mit einer nicht volatilen Kopie arbeiten. Wie das geht, findet man im Dokument im Anhang, Seite 15 Example 15. Optimization Using a Shadow Register Das ist zwar für einen anderen Prozessor, erklärt die Sache aber sehr gut!
Falk B. schrieb: > PORTA = (1<<PC5); ist eigentlich Unsinn, denn das Bit PC5 gibt es dort > nicht. Durch "Zufall" ist PC5 == PA5 ja, das stimmt! Kann man alles sehen, wie man will! ;) und der compiler macht es auch so. mir geht es nicht um geschwindigkeit, sondern um eine kompakte (eine zeile), leserliche schreibweise. ich danke dir für deine hilfreiche Antwort!
WENN man sich dazu entschließen sollte, das mit #defines und avr gcc Style zu machen, dann bitte richtig. Also eher so
1 | #define MY_REG_BIT_XYZ (1<<5)
|
2 | #define MY_REG_BIT_ABC (1<<3)
|
3 | |
4 | REG = MY_REG_BIT_XYZ | MY_REG_BIT_ABC; |
Die (1<<Bitnummer) Schreibweise ist nur eine Altlast der Atmel-Include Files! Sinnlose Tipparbeit. Die BitNUMMER braucht man in C so gut wie gar nicht, sie waren nur für die sbis/sbic cbi/sbi Befehle des AVR-Assemblers nötig.
Servus, auch die Einzelbits der Register sind definiert, so daß man sie in einem Ausdruck verrechnen kann, z.B.:
1 | INTCON |= _INTCON_T0IE_MASK | _INTCON_GIE_MASK; |
Wenn man für irgendwas die Bitnummer braucht, geht es so:
1 | INTCON |= 1 << _INTCON_GIE_POSITION; |
:
Bearbeitet durch User
Thomas E. schrieb: > auch die Einzelbits der Register sind definiert, so daß man sie in > einem Ausdruck verrechnen kann, z.B.: [...] habs eben auch entdeckt. durch die strikte struktur gibt es eigentlich wirklich keine verwechselungen... neben POSN (POSITION) und MASK gibt es auch noch SIZE (bzw. LENGTH). ich denke das kann sehr hilfreich sein. im vergleich zu gcc erscheint es mir sehr "diszipliniert". aber ob es mir gefällt... wer weiß! xD ich denke nach ein paar programmen hat man das auch verinnerlicht. nicht, dass es mir dann bei atmel "komisch" vorkommt! :D
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.