XC8 compiler - Register schreiben wie bei Atmel

Gast #4527750
Lesenswert?

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?
Gast #4527776
Lesenswert?

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?
#4527806
Lesenswert?

@  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!
Angehängte Dateien:
Gast #4527824
Lesenswert?

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!
#4527880
Lesenswert?

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.
Gast #4528272
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren