Forum: Mikrocontroller und Digitale Elektronik sbi und cbi in C


von C-Bastler (Gast)


Lesenswert?

Hallo,

hab grad festgestellt, dass gcc-avr Sequenzen wie
1
PORTB |= (1<<PORTB3)
je nach Laune als
1
sbi PORTB,PORTB3
oder als (sinngemäß)
1
in r16,PORTB
2
ori r16,PORTB3
3
out PORTB,r16
übersetzt.

Wie kann ich ihn "zwingen", die erste Form zu verwenden?

Im C-Tutorial steht:
"In Quellcodes, die für ältere Version den des avr-gcc/der avr-libc 
entwickelt wurden, werden einzelne Bits mittels der Funktionen sbi und 
cbi gesetzt bzw. gelöscht. Beide Funktionen sind in aktuellen Versionen 
der avr-libc nicht mehr enthalten und auch nicht mehr erforderlich."

Dieses "nicht mehr erforderlich" wundert mich grad, weil ich genau diese 
Funktionen brauche und keine Alternative kenne. Der betreffende Port 
wird nämlich auch aus einer Interrupt-Routine heraus genutzt, ich kann 
mit hier keine Zugriffsüberschneidungen erlauben.

Habt ihr eine Idee?

von H.Joachim S. (crazyhorse)


Lesenswert?

inline-Assembler?

von Sven P. (Gast)


Lesenswert?

C-Bastler schrieb:
> Wie kann ich ihn "zwingen", die erste Form zu verwenden?
Garnicht.
Die Variante mit 'or' verwendet er gerne, wenn mehrere Bits zugleich 
bearbeitet werden.


> Der betreffende Port
> wird nämlich auch aus einer Interrupt-Routine heraus genutzt, ich kann
> mit hier keine Zugriffsüberschneidungen erlauben.
In einer Interrupt-Routine wird dir auf dem AVR normalerweise auch 
niemand mehr dazwischenfunken. Oder verschachtelst du die Interrupts?


> Habt ihr eine Idee?
Notfalls Inline-Assembler nehmen.

von holger (Gast)


Lesenswert?

Optimierung einschalten.
Bei einigen Ports (z.B. PORTF) geht cbi, sbi nicht mehr.

von Spess53 (Gast)


Lesenswert?

Hi

>Wie kann ich ihn "zwingen", die erste Form zu verwenden?

sbi und cbi können aber nur auf die untersten 32 IO-Register zugreifen. 
Darüber kannst du zwingen bis du schwarz wirst.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

C-Bastler schrieb:
> hab grad festgestellt, dass gcc-avr Sequenzen wie
1
PORTB |= (1<<PORTB3)
> je nach Laune als
1
sbi PORTB,PORTB3
> oder als (sinngemäß)
1
in r16,PORTB
2
ori r16,PORTB3
3
out PORTB,r16
> übersetzt.

Bei dem selben Controller und der selben Optimierungs-Einstellung?
Kann ich nur schwer glauben.

von C-Bastler (Gast)


Lesenswert?

Hallo & danke für die schnellen Antworten!

Sven P. schrieb:
> Die Variante mit 'or' verwendet er gerne, wenn mehrere Bits zugleich
> bearbeitet werden.

Richtig, ist mir auch aufgefallen.

> In einer Interrupt-Routine wird dir auf dem AVR normalerweise auch
> niemand mehr dazwischenfunken. Oder verschachtelst du die Interrupts?

Missverständnis. Es geht um Hauptprogramm und Interrupt-Routine. Beide 
verwenden unterschiedliche I/O-Pins, diese sind aber auf dem gleichen 
Port (8-Pin-ATtiny).

> Notfalls Inline-Assembler nehmen.

Wär eine Idee, hab ich nur noch nie gemacht... Ich kenne nur den 
"normalen" Assembler. Wie schreib ich das dann? - So?
1
asm volatile ("sbi PORTB,PORTB3");

"PORTB" hab ich als Makro (per #define). - Dann also so?
1
asm volatile ("sbi "LEDPORT","LEDPIN);

von holger (Gast)


Lesenswert?

Jetzt mal ganz langsam und ein Beispiel zeigen wo
der Compiler das macht was du beschreibst.

Also C Code und das Assembler Listing dazu.
Vieleicht gibt es eine ganz einfache Erklärung;)

von Stefan E. (sternst)


Lesenswert?

C-Bastler schrieb:
> Sven P. schrieb:
>> Die Variante mit 'or' verwendet er gerne, wenn mehrere Bits zugleich
>> bearbeitet werden.
>
> Richtig, ist mir auch aufgefallen.

Wie sollte er es da auch anders machen? Mehrere sbi hintereinander wären 
ja schließlich was grundlegend anderes, als im C-Code geschrieben wurde.
(Port-Pins gleichzeitig schalten <-> Port-Pins nacheinander schalten).

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
Noch kein Account? Hier anmelden.