Forum: Mikrocontroller und Digitale Elektronik Warteschleife mit C - wird von WinAVR wegrationalisiert!


von Alex (Gast)


Lesenswert?

Habe mich jetzt ewig damit rumgeschlagen um rauszufinden dass es die 
Optimierung des Codes war, der mir sämtlichen Spaß genommen hat.

Folgender Code ist mehr oder weniger aus dem Atmega-buch von G.Schmitt.

Er funktioniert standardmäßig nicht, auch der Debugger überspringt 
einfach die nms Befehle.

Nur wenn die Optimierungsstufe 0 ist, dann funktioniert es ungefähr. 
Bereits Stufe 1 (und voreingestelle S) rationalisieren die leere 
Schleife einfach weg.
Was kann ich jetzt tun ohne auf meine Optimierung zu verzichten?

Ich hatte es bereits mit __asm NOP; probiert, das kannte er nicht.

P.S: Ich versuche es bewusst ohne Timer zur Übung..
1
#include <avr/io.h>
2
//#include <avr/interrupt.h>
3
#define TAKT 16000000UL /* 16 Mhz-Takt; hier richtigen Wert eintragen */
4
5
6
7
//Subroutinen
8
void ms(void){unsigned int i; for (i=0; i<TAKT/6000; i++){};}
9
void nms(unsigned int count){unsigned int i; for(i=0;i<count;i++){ ms();}}
10
11
12
13
14
15
16
int main(void)
17
{
18
unsigned int hell;
19
hell=0;
20
    DDRD |= (1 << PD5); // PD0 als Ausgang festlegen
21
     DDRD |= (1 << PD6); // PD0 als Ausgang festlegen
22
        PORTD |= (1 << PD5); // PD0 aktivieren
23
       PORTD |= (1 << PD6); // PD0 aktivieren
24
 
25
26
    while(1) // Unendlich lang wiederholen
27
    {
28
PORTD |= (1 << PD5); // PD0 aktivieren
29
30
nms(1000);
31
32
PORTD &= ~(1 << PD5);
33
nms(1000);  
34
35
} 
36
37
}

von *.* (Gast)


Lesenswert?

Versuch's mal mit "volatile".
1
//Subroutinen
2
void ms(void){volatile unsigned int i; for (i=0; i<TAKT/6000; i++){};}
3
void nms(unsigned int count){volatile unsigned int i; for(i=0;i<count;i++){ ms();}}

von *.* (Gast)


Lesenswert?

Nachtrag:

Das kennt er bestimmt
1
asm volatile ("nop" ::);

von *.* (Gast)


Lesenswert?

Nachtrag 2: (nein, ich mag mich nicht anmelden!)

Eigentlich sollte einmal das Schlüsselwort "volatile" genügen.
1
//Subroutinen
2
void ms(void){volatile unsigned int i; for (i=0; i<TAKT/6000; i++){};}
3
void nms(unsigned int count){unsigned int i; for(i=0;i<count;i++){ ms();}}

von Oliver (Gast)


Lesenswert?

>P.S: Ich versuche es bewusst ohne Timer zur Übung..

Wenn das Übungsziel war, selber zu erfahren, warum man für solche 
Verzögerungen die Funktionen aus delay.h nutzen soll, hast du bestanden.

Oliver
P.S. Eine Antwortautomatik, die auf einen Thread mit dem Wort "Schleife" 
und/oder "Optimierung" im Titel eine Beitrag mit dem Wort "volatile" 
erzeugt, wäre mal ein Fortschritt :-)

von Einer (Gast)


Lesenswert?

Wahrscheinlich nicht da das beide i lokal sind.

von ... .. (docean) Benutzerseite


Lesenswert?

http://www.gnu.org/savannah-checkouts/non-gnu/avr-libc/user-manual/group__util__delay.html

Du brauchst das Rad nicht neu erfinden...

Achtung aufpassen wenn du den Funktionen eine Variable übergibst wird 
die float lib eingebunden

von Johannes M. (johnny-m)


Lesenswert?

Hat es sich immer noch nicht herumgesprochen, dass solche selbstgebauten 
Warteschleifen nicht nur Optimizer-Futter sind, sondern auch noch 
ausgesprochener Murks? Es gibt in der util/delay.h einen ganzen Haufen 
Funktionen für genau definierte Wartezeiten, die nicht wegoptimiert 
werden!

EDIT:
docean war schneller...

Aber korrekt: Die Funktionen müssen mit konstantem Parameter aufgerufen 
werden und die Optimierung muss eingeschaltet sein. Wenn man Variable 
delays braucht, kann man ein delay mit fester Zeit in einer Schleife 
mehrmals aufrufen.

von Alex (Gast)


Lesenswert?

Okay, da habe ich mal versucht vorbildlich zu sein und mich vorher 
belesen und das Buch macht es so. Schade.
Ohne OPtimierung ist die delay.h ein ganz schöner Ressourcenfresser, 3kb 
:-) Na gut dafür gibt es ja Optimierung.

Dankeschön.

von Johannes M. (johnny-m)


Lesenswert?

Alex wrote:
> Ohne OPtimierung ist die delay.h ein ganz schöner Ressourcenfresser, 3kb
> :-) Na gut dafür gibt es ja Optimierung.
Ohne Optimierung funktioniert die delay.h auch gar nicht richtig! Die 
Optimierung ist für die Funktionalität zwingend erforderlich. Wenn die 
delay.h eingebunden ist, aber die Optimierung deaktiviert ist, sollte 
normalerweise sogar eine Warnmeldung ausgegeben werden.

von Oliver (Gast)


Lesenswert?

>void ms(void){unsigned int i; for (i=0; i<TAKT/6000; i++){};}

DAS steht so in einem Buch? Abgesehen von dem fehlenden volatile stellt 
sich da nämlich noch die Frage, wie lange eine "ms" sein soll. 
Millisekunden sind es auf jeden Fall nicht, und Mikrosekunden auch 
nicht.

Oliver

von Falk B. (falk)


Lesenswert?

@Alex (Gast)

>Ohne OPtimierung ist die delay.h ein ganz schöner Ressourcenfresser, 3kb
>:-) Na gut dafür gibt es ja Optimierung.

Nöö, siehe

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

MFG
Falk

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.