Forum: Mikrocontroller und Digitale Elektronik Am Port klappern


von Oktoberfestbesucher (Gast)


Lesenswert?

Hallo,
ich fummel mit dem ATtiny25 rum, um in die Materie rein zu kommen.
Bisher habe ich wenn ich einen Port setzen / löschen wollte das so 
gemacht:
1
#define LED_rot_an   {PORTB &= ~(1 << DDB4);}
2
#define LED_rot_aus   {PORTB |=  (1 << DDB4);}

Jetzt bin ich in der Instruction Set Summary auf die Befehle
SBI P,b Set Bit in I/O Register und
CBI P,b Clear Bit in I/O Register
gestossen.
Wie kann ich den Compiler (GCC = AVRWIN) überreden diese befehle zu 
benutzen?
1
#define LED_rot_an {asm volatile("CBI   PORTB,4");}
gibt leider Fehlermeldung.
Wie geht die richtige Schreibweise?

von Ch D. (chrisu) Benutzerseite


Lesenswert?

Hi,
Mit dieser Schreibweise funktioniert es bei mir.
__asm("nop");

von Timmo H. (masterfx)


Lesenswert?

Der Compiler sollte das schon so automatisch aus deinem ersten Ansatz 
machen.
Zudem kann man auch über C bereits diese Makros aufrufen ( cbi() und 
sbi()) wobei das nicht bei jedem Compiler geht.

von Karl H. (kbuchegg)


Lesenswert?

Oktoberfestbesucher schrieb:

> Wie geht die richtige Schreibweise?
1
#define LED_rot_an    do {PORTB &= ~(1 << PB4);} while( 0 )
2
#define LED_rot_aus   do {PORTB |=  (1 << PB4);} while( 0 )

Den Rest erledigt dein Compiler. Compilerbauer sind ja auch nicht doof.

von Oliver (Gast)


Lesenswert?

Timmo H. schrieb:
> Den Rest erledigt dein Compiler.

wenn du den auch optimieren lässt. Sonst produziert der da tatsächlich 
sehr länglichen Code.

Oliver

von syn_error (Gast)


Lesenswert?

>ich fummel mit dem ATtiny25 rum, um in die Materie rein zu kommen.
imho würde ich empfehlen um in die materie reinzukommen mit assembler 
die ersten gehversuche zu machen.

zu deinem problem, google man nach gcc inline-assembler.

von ... .. (docean) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
>> Wie geht die richtige Schreibweise?
> #define LED_rot_an    do {PORTB &= ~(1 << PB4);} while( 0 )
> #define LED_rot_aus   do {PORTB |=  (1 << PB4);} while( 0 )

Was soll das do..while da?

von Karl H. (kbuchegg)


Lesenswert?

Oliver schrieb:
> Timmo H. schrieb:
>> Den Rest erledigt dein Compiler.
>
> wenn du den auch optimieren lässt.

Du hast natürlich recht.
Allerdings gehe ich schon davon aus, dass man sein Programm durch den 
Optimizer jagt. Schliesslich haben eine Menge Leute eine Menge 
Gehirnschmalz da rein gesteckt, so dass ich mich auf das Problem 
konzentrieren kann anstatt auf die vielen kleinen Details und der 
Compiler sorgst dafür, dass meine Programmidee so gut wie möglich auf 
der Assembler-Ebene umgesetzt wird.

von Karl H. (kbuchegg)


Lesenswert?

... ... schrieb:
> Karl heinz Buchegger schrieb:
>>> Wie geht die richtige Schreibweise?
>> #define LED_rot_an    do {PORTB &= ~(1 << PB4);} while( 0 )
>> #define LED_rot_aus   do {PORTB |=  (1 << PB4);} while( 0 )
>
> Was soll das do..while da?

Lass es weg und schreib mal
1
   if( i == j )
2
     LED_rot_an;
3
   else
4
     LED_rot_aus;

und erfreu dich an der Fehlermeldung, dass ein else existiert, für das 
es kein if gibt.
Oder noch fieser
1
   if( k == 0 )
2
     if( i == j )
3
       LED_rot_an;
4
     else
5
       LED_rot_aus;

das else gehört zum if( k == 0 ).
Nicht ganz das, was du dir vorgestellt hast, oder?

Warum das so ist?
Mach die Textersetzung und sieh selber.

von Oliver (Gast)


Lesenswert?

grr..

Karl heinz Buchegger schrieb:
> Den Rest erledigt dein Compiler.

Die Zitatfunktion hier im Forum ist nicht idiotensicher ...

syn_error schrieb:
> imho würde ich empfehlen um in die materie reinzukommen mit assembler
> die ersten gehversuche zu machen.

Ich nicht. Ich würde, um in die Materie reinzukommen, erst einmal völlig 
die Finger von Assembler lassen. Planloses vermischen von C und 
Assembler bringt, wie dieses Beispiel hier ja auch wieder zeigt, gar 
nichts.

Oliver

von ... .. (docean) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Nicht ganz das, was du dir vorgestellt hast, oder?
1
#define LED_rot_an   PORTB &= ~(1 << DDB4)
2
#define LED_rot_aus   PORTB |=  (1 << DDB4)

so finde ich die defines auch besser, oder ist das auch doof/ungünstig?

von Karl H. (kbuchegg)


Lesenswert?

... ... schrieb:
> Karl heinz Buchegger schrieb:
>> Nicht ganz das, was du dir vorgestellt hast, oder?
>
>
1
> #define LED_rot_an   PORTB &= ~(1 << DDB4)
2
> #define LED_rot_aus   PORTB |=  (1 << DDB4)
3
>
>
> so finde ich die defines auch besser, oder ist das auch doof/ungünstig?

Nein.
In dem Fall ist das ok und völlig identisch zu der Version mit den { } 
rundum. Aber wenn man schon { } macht (weil man zb mehrere Anweisungen 
durch das Makro einbringen möchte) dann muss man das auch richtig machen 
:-)

Entscheidend ist, dass ich bei der Makro-Verwendung noch einen ; hinten 
drann machen kann, ohne dass sich die Semantik ändert

von Hc Z. (mizch)


Lesenswert?

Oktoberfestbesucher schrieb:
> #define LED_rot_an {asm volatile("CBI   PORTB,4");}
> gibt leider Fehlermeldung.
> Wie geht die richtige Schreibweise?
1
cbi _SFR_IO_ADDR(PORTB),4

von Oktoberfestbesucher (Gast)


Lesenswert?

Hc Zimmerer schrieb:
> cbi _SFR_IO_ADDR(PORTB),4

habe dieses probiert,
1
#define LCD_Data_0  asm volatile("cbi _SFR_IO_ADDR(PORTB),4");
geht überhaupt nicht.
Fehlermeldungen zuhauf.
Habe AVR Studio 4 und GCC Compiler
Mein MCU ist ATtiny25

von Oliver (Gast)


Lesenswert?

Oktoberfestbesucher schrieb:
> habe dieses probiert,#define LCD_Data_0  asm volatile("cbi _SFR_IO_ADDR 
>PORTB),4");
>
> geht überhaupt nicht.

Natürlich geht das nicht. cbi_SFR_IO_ADDR ist eine C-Funktion (bzw. ein 
makro) aus der avrlibc.

Lass doch den Assembler Assembler sein, und schreib dein Programm in C. 
Der C-Compiler kennt wirklich alle erforderlichen Assemblerbefehle, und 
weiß die auch zu nutzen. Auch sbi und cbi.

Schau dir mal im .lss-File an, was der Compiler aus der Zeile
1
PORTB &= ~(1 << DDB4);

mit eingeschalteter Optimierung macht.

Oliver

von Oktoberfestbesucher (Gast)


Lesenswert?

Oliver schrieb:
> Schau dir mal im .lss-File an, was der Compiler aus der Zeile
> PORTB &= ~(1 << DDB4);
> mit eingeschalteter Optimierung macht.
>
> Oliver

1
 c0:  c4 98         cbi  0x18, 4  ; 24


Sehr guter Tip,
ich staune Bauklötze, woher weis der Compiler so schlau, was ich will?

von Karl H. (kbuchegg)


Lesenswert?

Oktoberfestbesucher schrieb:
> Oliver schrieb:
>> Schau dir mal im .lss-File an, was der Compiler aus der Zeile
>> PORTB &= ~(1 << DDB4);
>> mit eingeschalteter Optimierung macht.
>>
>> Oliver
>
>
>
1
>  c0:  c4 98         cbi  0x18, 4  ; 24
2
>
>
>
> Sehr guter Tip,
> ich staune Bauklötze, woher weis der Compiler so schlau, was ich will?

Du willst mit

    PORTB &= ~(1 << 4);

Das Bit 4 am PortB auf 0 setzen. Das hier ist die C-Schreibweise dafür. 
Irgendein kluger Mensch hat sich mal überlegt, dass wenn man das plain 
Vanilla übersetzt, da immer diese Sequenz rauskommt

     IN      r_irgendwas, PORTB
     ANDI    r_irgendwas, ~(1<<wert)
     OUT     PORTB, r_irgendwas

und dass man diese Sequenz gefahrlos gegen

     cbi     PORTB, wert

ersetzen kann. Macht dasselbe, ist aber kürzer (und versaut keine Flags 
bei der Ausführung). Alles was er tun muss, ist während der 
Optimierungsphase nach solchen Sequenzen zu suchen und die Ersetzung 
vorzunehmen, ehe dann das endgültige Programm in Maschinensprahce 
erzeugt  wird.

Das sagen wir doch schon die ganze Zeit: Compilerbauer sind keine 
Volltrottel. Die haben noch ganz andere Optimierungstricks auf Lager.

(Compilerbauer mögen mir verzeihen, wenn ich das jetzt absichtlich 'ein 
klein wenig vereinfacht' darstelle.)

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.