mikrocontroller.net

Forum: Compiler & IDEs verwunderter C - Anfänger


Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
mit Assembler habe ich schon einiges programmiert, nun wollte ich mir 
mal anschauen welche vor und Nachteile C mit sich bringt. Allerdings bin 
ich hier (zu meiner Verwunderung nicht weit gekommen). Hier mal ein 
Beispiel:
#include <avr/io.h>
#define TAKT 14745600UL
 
void main (void)
{
   DDRC  = 255;
   PORTC = 0;
   
 
   while(1) 
   {
   warte16( );
   PORTC++;
   }
}

void warte16(void)
{
unsigned long i;
for (i = 0; i < 200000; i++);
}

dieser kleine Dualzähler funktioniert so wunderbar, wenn ich allerdings 
erst PORTC++; und dann warte16( ); aufrufe, leuchten alle LED´s an Port 
c und es scheint nichts mehr gezählt zu werden.

Solche merkwürdigen Fehler (oder steckt da eine Logik dahinter - ich 
hoffe es) gab es noch einige, wodurch  ich lieber wieder zu Assembler 
zurückkehre, andererseits kann ich mir auch nicht vorstellen, das C so 
voller Probleme steckt, wie es mir im ersten Moment erscheint.

Vielleicht kann mir ja jemand mein obiges Problemchen erläutern, so dass 
ich doch noch Lust auf C bekomme!

Würde mich freuen...

grüße
Andreas

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der zählt durchaus. Nur schneller als dir lieb ist.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber warum macht es einen unterschied, ob ich warten16(); vor oder nach 
dem setzen vom PORT aufrufe????

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas wrote:
> aber warum macht es einen unterschied, ob ich warten16(); vor oder nach
> dem setzen vom PORT aufrufe????

Vermutlich schlägt dir der Optimizer ein Schnippchen! Versuche (wie 
schon erwähnt) die integrierten _delay_xy Funktionen zu benutzen. 
(Obiger Link)

PS: Vergiss aber nicht F_CPU mit anzugeben. (Bei AVR-Studio geht das in 
den Project Settings. Wo du hoffentlich auch den richtigen AVR-Typen 
eingetragen hast. Ohne AVR Studio benutzt du einfach ein Define an 
oberster Stelle)

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit volatile vor der Deklaration Zählvariable wird wohl dann auch 
klappen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian R. wrote:
> Mit volatile vor der Deklaration Zählvariable wird wohl dann auch
> klappen.

Volatile hat da nix zu suchen. Oder wird dann die for-schleife nicht 
wegoptimiert?

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ...Oder wird dann die for-schleife nicht wegoptimiert?

So isses

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, dann nehme ich sofort alles zurück und behaupte das Gegenteil! ;)

Autor: Stefan Salewski (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich jetzt nicht ganz verstanden?
Die Warteschleife des urspünglichen Posters wird anfangs brav 
ausgeführt, und wenn der die Reihenfolge der zwei Anweisungen 
vertauscht, wird die Warteschleife total wegoptimiert? Das wäre doch 
wirklich seltsam. (Ich kanns derzeit nicht testen, ich habe derzeit nur 
avr-gcc 3.4.6, da bleiben Warteschleifen erhalten.)

Autor: Xenu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Stefan Salewski

Ich habe mir mal den generierten Assemblercode angeschaut.

Dieses Verhalten hat wohl was mit dem Funktions-Inlining zu tun.
So wie es ausschaut ist Inlining wohl standardmäßig eingeschaltet.

Also schaut der Code mit "warte16()" vor "PORTC++" quasi so aus:
  unsigned long i;
  for (i = 0; i < 200000; i++);
  PORTC++;

Und offenbar ist es so, das der gcc diese an sich nutzlose Schleife 
nicht wegoptimiert (wie er es eigentlich sollte, wenn i nicht als 
volatile deklariert ist). Wenn man sie hinter "PORTC++" schreibt macht 
er das nämlich schon.

Wenn man bei warte16() das inlining abschaltet, wird sie in beiden 
Fällen (vor/hinter PORTC++) tatsächlich auch aufgerufen, besteht aber 
nur aus "ret".

Also immer volatile bei Warteschleifen benutzen oder gleich die 
mitgelieferten Delayfunktionen benutzen.

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.