Hallo Leute.
Ich habe momentan ein Problem mit meinem Code. Es soll eine LED über
eine Geradengleichung gedimmt werden. Es funktioniert aber nicht und ich
weiß nicht wieso. Hab schon nen Debugger rangehangen, aber da ich mich
damit (noch) nicht so auskenne hilft mir das nicht weiter.
Ich vermute es liegt unter anderem an der Optimierung. Jene kann ich
aber nicht ausstellen, da sonst der Code zu groß ist. Die Variable
"zaehler" ist immer "out of scope".
Als Anmerkung sei gesagt, dass "sek" in einer ISR sekündlich hochgezählt
wird.
Es wäre schön, wenn einer ne Idee hat :-)
Hier mal der Codeausschnitt:
1
//globale Variablen
2
volatileuint8_tsek=0,abschnitt=0;
3
uint8_tintervalle_werte[7]PROGMEM={0,100,255,100,150,100,50};//gibt die Stützstellen der y-Werte (Helligkeit) an
4
uint16_tintervalle_t[7]PROGMEM={0,5,10,15,33,37,60};// gibt die Stützstellen der x-Werte (Zeit) an
5
6
// Zeit lesen
7
voidget_time(void){
8
volatileuint8_ti;
9
for(i=0;i<7;i++){
10
if(sek<intervalle_t[i]){
11
abschnitt=i;
12
break;
13
}
14
}
15
}
16
17
// Wert lesen und übergeben
18
uint8_tget_value(void){
19
20
get_time();
21
22
volatileint16_tergebnis;// ergebnis = ( (zaehler/nenner) / 1000 ) + n
> OCR1A = pgm_read_word(&pwmtable[*result*]);
Woher kommt result ???
Da musst Du schon ein bisschen mehr Code posten um etwas nachvollziehen
zu können....
> uint16_t intervalle_t[7] PROGMEM [..]> if ( sek < intervalle_t[i]) {
^
das (und sämtliche andere Zugriffe auf den PROGMEM) dürfte so nicht
funktionieren wie erwartet -> pgm_read_*()
..weiter hab ichs mir noch nicht angesehen..
Peter schrieb:> Woher kommt result ???
Es muss natürlich Ergebnis heißen.
g457 schrieb:> das (und sämtliche andere Zugriffe auf den PROGMEM) dürfte so nicht>> funktionieren wie erwartet -> pgm_read_*()
Das hab ich gerade gesehen und bin dabei es zu ändern.
A. K. schrieb:> Was sollen denn diese ganzen volatiles für lokale Variablen
Wenn ich die Variablen nicht volatile hatte wurden sie vom Compiler
wegveroptimiert. Zumindest waren sie "out of scop" auch innerhalb der
fkt.
Ich änder gerad den Code nochmal um und wenn ich nicht weiter weiß poste
ich ihn wieder :-)
Danke schonmal. Das mit dem progmem hab ich nicht gesehen... Wenn man
das ganze Woche mit C# rummacht vergisst man sowas ganz schnelle -.-
... ... schrieb:> du weißt aber das du die Helligkeit und Storm/Spannung nicht linear>> zusammenhängen?
deswegen wird doch der Wert zum Schluss durch ein Lookuptable übergeben!
Ich habe den Code wieder aktualisiert und er funktioniert jetzt mit der
Einschränkung, dass ich nicht weiß, warum die Variable "zaehler" ständig
"not valid" im AVR Studio angezeigt wird. Liegt es daran, dass es eine
32bit Variable ist? Habe ich falsch gecastet?
Hier nochmal der aktualisierte Code mit den behobenen Fehlern:
1
//globale Variablen
2
volatileuint8_tsek=0,abschnitt=0;
3
volatileint16_tVerschiebung=0;
4
5
uint8_tintervalle_werte[7]PROGMEM={0,100,255,100,150,100,50};//gibt die Stützstellen der y-Werte (Helligkeit) an
6
uint16_tintervalle_t[7]PROGMEM={0,5,10,15,33,37,60};// gibt die Stützstellen der x-Werte (Zeit) an
7
8
// Zeit lesen
9
voidget_time(void){
10
volatileuint8_ti;
11
for(i=0;i<7;i++){
12
if(sek<intervalle_t[i]){
13
abschnitt=i;
14
break;
15
}
16
}
17
}
18
19
// Wert lesen und übergeben
20
uint8_tget_value(void){
21
22
get_time();
23
24
volatileint16_tergebnis;// ergebnis = ( (zaehler/nenner) / 1000 ) + n
Phil schrieb:> Ich habe den Code wieder aktualisiert und er funktioniert jetzt mit der> Einschränkung, dass ich nicht weiß, warum die Variable "zaehler" ständig> "not valid" im AVR Studio angezeigt wird. Liegt es daran, dass es eine> 32bit Variable ist? Habe ich falsch gecastet?
Es liegt wahrscheinlich daran, dass du optimierten Code debugst und der
Optimizer einen Weg gefunden hat, wie er die Variable wegeliminiert.
Wenn du den Optmizer eingeschaltet hast, kann, darf und wird der
Optimizer den Code umstellen und Variablen entfernen.
Und warum sollte man beim Debuggen die Optimierung abschalten?
Ich versteh schon, dass der hier und da ein wenig optimiert. Aber ich
versteh nicht wie man vorgehen soll wenn der Code wächst und wächst und
man einfach nicht mehr die Optimierung abschalten kann, weil ebn sonst
der uc voll ist und sich gar nicht mehr flashen lässt...
Komisch finde ich ja, dass obwohl die Variable volatil ist, der Compiler
sie wohl TROTZDEM wegoptimiert.
Phil schrieb:> Und warum sollte man beim Debuggen die Optimierung abschalten?>> Ich versteh schon, dass der hier und da ein wenig optimiert.
Nicht hie und da!
Der Optimizer rührt da anständig um!
> Aber ich> versteh nicht wie man vorgehen soll wenn der Code wächst und wächst und> man einfach nicht mehr die Optimierung abschalten kann, weil ebn sonst> der uc voll ist und sich gar nicht mehr flashen lässt...
ev. hilft es, nur Teile des Codes zu optimieren.
> Komisch finde ich ja, dass obwohl die Variable volatil ist, der Compiler> sie wohl TROTZDEM wegoptimiert.
Da es sich hier um eine Funktionslokale Variable handelt kann der
Optimizer den kompletten Lebenszyklus der Variablen überblicken.
Ich rate jetzt mal ein wenig.
Wenn der Optimizer den Code so umstellt
ändert sich am Ergebnis nichts.
Aber: Dadurch, dass er das Berechnen von 'zaehler' nach hinten
verschoben hat, hat er das Ergebnis nach der Berechnung bereits in einem
Register vorliegen. Und da es dort bereits liegt, braucht er es in der
nachfolgenden Division nicht erneut laden -> kürzerer Code. Damit ist
aber auch klar, da die Variable sonst nirgends mehr benutzt wird, dass
niemand die Variable braucht. Insbesondere ist das 'volatile' an dieser
Stelle sinnlos, da ausserhalb der Funktion sowieso niemand auf diese
Variable zugreifen kann und diese Variable (als funktionslokale
Variable) auch sonst nicht erreichbar ist (zb über einen Pointer), da
keine Funktion aufgerufen wird, der die Adresse dieser Variablen
übergeben wird.
Du unterschätzt gewaltig, was der Optimizer mit deinem Code alles machen
kann und wieviel Gehirnschmalz da mitlerweile drinnen steckt.
Phil schrieb:> Komisch finde ich ja, dass obwohl die Variable volatil ist, der Compiler> sie wohl TROTZDEM wegoptimiert.
Wenn dich das wundert wundert mich nix ;P
volatile heißt doch nur das sich die Variable außerhalb des
Sichtbereiches des Compilers ändern kann.
Wenn du die Variable aber nie liest (und diese Funktionslokal ist) kann
er diesen Ausdruck:
1
ergebnis=((zaehler/nenner)/1000)+n;
2
OCR1A=pgm_read_word(&pwmtable[result]);
3
returnergebnis;
Wunderbar optimieren zu:
1
OCR1A=pgm_read_word(&pwmtable[result]);
2
return((zaehler/nenner)/1000)+n;
(Wobei wir immer noch nicht wissen woher eigentlich result kommt...)
Phil schrieb:> versteh nicht wie man vorgehen soll wenn der Code wächst und wächst und> man einfach nicht mehr die Optimierung abschalten kann, weil ebn sonst> der uc voll ist und sich gar nicht mehr flashen lässt...
Dein "Problem" ist denke ich einfach das du einen riesen Haufen (manche
nenen es auch Codewust) an Abhängigkeiten zusammenklatscht, gewürzt mit
ein paar Annahmen und Try&Error Programmierung.
Normalerweise versucht man Funktionen so zu gestalten das diese
möglichst eigenständig arbeiten und auch getestet werden können. Wenn
ich dann weiß dass die Funktion korrekt funktioniert kann ich diese in
anderen Programteilen dann nutzen und muss nicht das gesamte Programm
debuggen.
Karl heinz Buchegger schrieb:> ev. hilft es, nur Teile des Codes zu optimieren.
optimieren.. ich hoffe du meinst compilieren bzw. debuggen. Oder kann
man tatsächlich die Optimierungsstufe für ganze Codeabschnitte
einstellen? Wär ja cool. Glaub aber kaum, dass das geht.. Wegen der
"Ganzheitlichkeit" :-)
Also ich habe jetzt den Code in ein eigenes Projekt ausgelagert und
siehe da. Es funktioniert auch OHNE volatile und alle Variablen
EINSCHLIESSLICH "zaehler" haben einen resonablen Wert.
Die große Frage für mich lautet jetzt.
Kann ich nun ruhigen Gewissens den Code in meinem eigentlichen Projekt
so lassen, oder muss ich "Angst" haben, dass mir der Optimierer wieder
nen fetten Strich durch die Rechnung macht. Nicht optimiert und
ausgelagert läuft er.
Läubi .. schrieb:> Dein "Problem" ist denke ich einfach das du einen riesen Haufen (manche>> nenen es auch Codewust) an Abhängigkeiten zusammenklatscht, gewürzt mit>> ein paar Annahmen und Try&Error Programmierung.
Kurzn: Anfänger. Japp. Das bin ich :-)
Der Optimizer macht dir niemals ein Strich durch die Rechnung (mal
abgesehen, von globalen Variablen und Interrupts, aber das tut hier nix
zur Sache).
Dass der Optimizer Variablen rausschmeißt, ändert nichts an der
funktionalität des Codes. Allerdings kannst du sie dann im debugger
nicht mehr anzeigen lassen, wie du festgestellt hast. Das ist aber kein
Hinweis darauf, dass der Code nicht funktioniert.
Also:
- Wenn du bei einer Variable "Not in Scope" oder "Location not Valid"
angezeigt bekommst, is das kein Grund zur Sorge. Das hat alles seine
Richtigkeit.
- Wenn du aber zum Debuggen unbedingt den Inhalt einer Variabelen sehen
möchtest, kannst du sie (temporär!) als Volatile deklarieren. In den
meisten Fällen wird sie dann nicht wegoptimiert. Durch das Volatile hast
du dir nur die Möglichkeit geschaffen, die Variable im Debugger
anzuzeigen, aber keine Funktionalität des Codes geändert.