mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Am Port klappern


Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define LED_rot_an   {PORTB &= ~(1 << DDB4);}
#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?
#define LED_rot_an {asm volatile("CBI   PORTB,4");}
gibt leider Fehlermeldung.
Wie geht die richtige Schreibweise?

Autor: Ch D. (chrisu) Benutzerseite
Datum:

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

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oktoberfestbesucher 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 )

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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: syn_error (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   if( i == j )
     LED_rot_an;
   else
     LED_rot_aus;

und erfreu dich an der Fehlermeldung, dass ein else existiert, für das 
es kein if gibt.
Oder noch fieser
   if( k == 0 )
     if( i == j )
       LED_rot_an;
     else
       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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ... ... (docean) Benutzerseite
Datum:

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

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... ... schrieb:
> Karl heinz Buchegger schrieb:
>> Nicht ganz das, was du dir vorgestellt hast, oder?
>
>
> #define LED_rot_an   PORTB &= ~(1 << DDB4)
> #define LED_rot_aus   PORTB |=  (1 << DDB4)
> 
>
> 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

Autor: Hc Zimmerer (mizch)
Datum:

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

Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
> cbi _SFR_IO_ADDR(PORTB),4

habe dieses probiert,
#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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
PORTB &= ~(1 << DDB4);

mit eingeschalteter Optimierung macht.

Oliver

Autor: Oktoberfestbesucher (Gast)
Datum:

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

 c0:  c4 98         cbi  0x18, 4  ; 24


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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
>
>
>
>  c0:  c4 98         cbi  0x18, 4  ; 24
> 
>
>
> 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.)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.