__builtin_avr_delay_cycles expects an integer constant
und das 6mal. die Meldung bezieht sich ganz oben auf die Variable 'ms'
Die Meldung bedeutet, soweit ich gelesen hab, dass die Funktionen eine
Konsztante als Parameterbraucht und keine Variable.
Deswegen hab ich ganz oben mal in ein delay y geschrieben.
Fehlermeldung bleibt.
aber warum bringt er hier keine Fehlermeldung.? :
verwirrter schrieb:> aber warum bringt er hier keine Fehlermeldung.?
'y' wird nicht weiter gebraucht, deshalb wird der Wert gleich nach
delay_ms übernommen.
Glück gehabt ;-)
und warum gehts hier nicht.?
int y = 1;
void ledon0(int ms){
PORTD &= ~_BV(PD0); _delay_ms(y);
}
hier wird y doch auch nicht weiter gebraucht
was kann man machen?
Weil dein Compiler eine Datenfluss Analyse gemacht hat.
Die hat ergeben, dass sich der Wert von y innerhalb dieser Funktion
nicht ändern kann und y daher immer den Wert 500 haben wird.
Daher kann der COmpiler die Variable y komplett eliminieren und überall
dort, wo bisher y stand direkt die 500 einsetzen.
verwirrter schrieb:> und warum gehts hier nicht.?>> int y = 1;>> void ledon0(int ms){> PORTD &= ~_BV(PD0); _delay_ms(y);> }>> hier wird y doch auch nicht weiter gebraucht
sagt wer?
Ich schreib ein zweites C-File, das so aussieht
1
externinty;
2
3
voidfoo()
4
{
5
y=20;
6
}
und rufe die Funktion foo von main aus auf.
Und schon ist es dahin mit deiner Annahme, dass y immer den Wert 1 haben
wird.
Da y hier eine globale Variable ist, kann nichts und niemand sicher
stellen, dass diese Variable nicht von irgendwo anders verändert wird.
Ganz im Gegensatz zu hier
1
intbar()
2
{
3
inty=1;
4
5
...
hier ist y eine funktionslokale Variable. Es gibt keine Möglichkeit von
ausserhalb diese Variable zu verändern. Wenn der Compiler die Funktion
bar analysiert, kennt er die ganze Geschichte, was mit diesem y je
passieren wird.
verwirrter schrieb:> gut zu wissen...>>> aber irgendeine lösung muss es geben, da der code vor langer zeit> schonmal funktionierte
Natürlich gibt es eine Lösung. Sogar mehrere
1) mach halt keine Variable
Was ist denn offensichtlich der Zweck dieser Variablen?
Der Zweck ist ja wohl, dass du quer durchs ganze Programm immer den
gleichen Zahlenwert hast, wo auch immer du y benutzt.
Jetzt willst du natürlich nicht den Zahlenwert überall direkt im
Programm stehen haben, weil das in einen Albtraum ausartet, wenn sich
der WErt mal ändert.
In so einem Fall kann man dann zb den Präprozessor benutzen, der durch
simple Textersetzung den konkreten Zahlenwert anstelle eines
Platzhalters im Programm einsetzt. Und zwar überall dort, wo dieser
Platzhalter vorkommt
2)
Du musst den Compiler davon überzeugen, dass es im Programm keine
Möglichkeit gibt, wie y jemals seinen Wert ändern könnte.
Dazu gibt es das Schlüsselwort 'const'.
1
constinty=1;
jetzt weiss der Compiler, dass du ihm die Zusicherung gibst, dass y
immer den gleichen Wert haben wird. Das bedeutet nicht unbedingt, dass
er dadurch immer bei _delay_ms( y ); diesen Zahlenwert auch benutzen
wird. Aber die Chancen stehen schon mal nicht schlecht - zumindest die
Voraussetzungen sind erst mal gegeben
Lösung 3)
getreu dem Motto
_delay_ms ist selten die richtige Lösung, oft aber das Problem!
ein kompletter Verzicht auf _delay_ms und statt dessen die
Implementierung nach den Regeln der Kunst mit einem Timer.
Bei Programmen, die ausser endlos ein paar LEDs blinken zu lassen, auch
noch was anderes tun sollen, ist das sowieso das Um- und Auf, wie man
eine derartige Funktionalität implementiert.
Lösung 4)
anstatt _delay_ms direkt zu verwenden, machst du dir eben eine delay
Funktion, der du die Anzahl der zu wartenden Millisekunden mitgibst. Die
realisiert diese Wartezeit, indem sie entsprechend oft _delay_ms(1)
aufruft. Denn 25 mal jeweils 1 Millisekunde gewartet sind in Summe auch
25 Millisekunden gewartet. Oder eben verallgemeinert: x mal 1
Millisekunde gewartet, ergibt eine totale Wartezeit von x Millisekunden
1
voiddelay(intms)
2
{
3
inti;
4
for(i=0;i<ms;i++)
5
_delay_ms(1);
6
}
Aber Achtung!
Die Zeiten werden nicht ganz genau stimmen, denn die for-Schleife
braucht ja auch ein bischen Zeit für sich.
> da der code vor langer zeit schonmal funktionierte
Nö. Dieser Code hat noch nie funktioniert.
Du magst ihn durch den Compiler gebracht haben, weil damals die Warnung
noch nicht eingebaut war, aber funktionieren ist anders.
Funktionieren bedeutet, dass nicht nur der Compiler seinen Segen gibt,
sondern das das Programm auch das tut, was drinnen steht.
Und wenn im Programm drinnen steht, dass 20 Millisekunden gewartet
werden soll, beim Nachmessen sich aber rausstellt, dass die Wartezeit in
Wirklichkeit 56 Millisekunden ist, dann kann man das nicht als
funktionieren bezeichnen.
Und genau das passiert nämlich, wenn die Angabe für _delay_ms keine
Zahlenkonstante ist: die tatsächlich realisierten Zeiten stimmen hinten
und vorne nicht.
"Funktionieren" - geht anders.
verwirrter schrieb:> volatile uint8_t i,p,pp,c,buf,ms,x;
Warum global und warum volatile?
Bei dem Code den du gepostet hast, gibt es keinen Grund weshalb die
Variablen global und/oder volatile sein sollten.
verwirrter schrieb:> volatile uint8_t ...,pp,...> pp=1000;
Und jetzt erklär doch mal, wie das jemals richtig Funktioniert haben
soll...
Wenn es jemals Funktioniert hat, dann hat es irgendwie Funktioniert und
mit viel Glück. Wertebereiche sollte man zumindestens ganz grob
kennen...
Schlag doch nochmal in deinem C-Buch nach... Und wenn du keins hast,
dann besorg dir eins.
Karl Heinz schrieb:> Natürlich gibt es eine Lösung. Sogar mehrere>> 1) mach halt keine Variable> ...
1a)
Falls man mit unterschiedlichen Zeiten experimentieren will, welche
(meistens) in einem Zusammenhang stehen, geht auch sowas:
verwirrter schrieb:> aber irgendeine lösung muss es geben, da der code vor langer zeit> schonmal funktionierte
In früheren Versionen der avr-libc/des Compilers wurde halt nicht mit
Fehler abgebrochen, sondern man bekam nur eine Warnung, und die Delays
waren alle falsch.