Hallo, bin keine C-Leuchte, arbeite aber trotzdem damit. Jetzt ist ein Problem aufgetaucht bei dem ich nicht weiter komme. Zur Illustration habe ich einen screen-shot angehängt. Ich verwende zwei Funktionen die ähnlich aufgerufen werden , in denen dieselbe Structur benutzt wird (im Bild unten) . Der Aufruf ist auch ziemlich gleich (im Bild oben). Das Ergebnis ist jetzt aber so, dass der grün umrahmte Ausfruf der grün umrahmten Funktion funktioniert, der rot umrahmte hingegen nicht. Im Bild rechts oben sieht man wie der Inhalt der Structur aussehen sollte (gelb), und wie er ist (rot). Bei der "grünen" Funktion stimmt alles prima überein. Die Adresse der Structur in der roten Funktion ist aus irgend einem grund falsch. Der Compiler ist GCCARM. Kann mir bitte jemand sagen was ich hier falsch mache? Danke
Mehr Quellcode wäre nicht schlecht. z.B. Zeilen 2000-2500 der Datei, welche die beiden Aufrufe tätigt.
Danke für's ansehen. Glaube nicht dass die Vorgeschichte was hilft. Es sind weitere Funktionen die nichts mit dem Aufruf zu tun haben. Aber bitte hier etwas mehr Code davor. Gruss
Wie wärs mit Text statt Bildern? Wo sind die Strukturen definiert?
In Bildern meine ich die Zusammehänge besser darstellen zu können. Der Text sagt meiner Meinung nach fast weniger. Hier die Struktur definition als Text typedef struct PID_DATA{ float f_lastProcessValue; //! Last process value, used to find derivative of process value. float f_sumError; //! Summation of errors, used for integrate calculations float f_P_Factor; //! The Proportional tuning constant, multiplied with SCALING_FACTOR float f_I_Factor; //! The Integral tuning constant, multiplied with SCALING_FACTOR float f_D_Factor; //! The Derivative tuning constant, multiplied with SCALING_FACTOR float f_maxError; //! Maximum allowed error, avoid overflow float f_maxSumError; //! Maximum allowed sumerror, avoid overflow } pidData_t; und struct PID_DATA tdr1_pid_struct; struct PID_DATA tdr2_pid_struct; Danke für die Hilfe.
Vielleicht noch eine Bemerkung die eventuell von Bedeutung ist, aber auf den ersten Blick gar nichts mit dem struct Problem zu tun hat. Die Parameter die ich beim Aufruf übergebe sind teilweise so definiert: z.B. f_pid1_solltempdiff typedef union _un_float_to_char { float fVal; u_char cVal[4]; }un_float_to_char; un_float_to_char f_pid1_solltempdiff; Normalerweise benutze ich die Variable so: f_pid1_solltempdiff.fVal = 1.234; Erst dachte ich beim Aufruf der Function mit dem struct Problem ich müsste das so machen: f_test = PID_Controller(f_pid1_solltempdiff.fVal, f_pid_tempdiff1_ist.fVal, &tdr1_pid_struct); Das lieferte aber auch falsche Werte in der PID_Controller Funktion. Nur so werden diese Parameter richtig übergeben: f_test = PID_Controller(f_pid1_solltempdiff, f_pid_tempdiff1_ist, &tdr1_pid_struct); Ist vielleicht ein anderes Problem, aber eventuell hilft es doch meinen "Verhau" zu ordnen. Warum das so ist weiss ich als Autodidakt leider nicht. Gruss
Sorry, mir das jetzt alles zusammenzureimen übersteigt meinen Alkoholvorrat. Falls du ein möglichst übersichtliches Codefragment, welches den Fehler immer noch zeigt, einstellen würdest, würden sich deine Chancen auf Hilfe erheblich verbessern... Ansonsten mal so in Blaue: Stack kaputt? Gruss
Werden tdr1_pid_struct und tdr2_pid_struct lokal in tdr.c definiert? Wenn beide hintereinander definiert werden, dann vertausch mal die Reihenfolge. Kann es sein, dass der RAM nicht reicht? Obwohl du &tdr2_pid_struct an PID_Controller(...) übergibts, zeigt diese nämlich auf NULL.
Martin, ja, werden sie. Habe sie testhalber vertauscht, aber leider selbes Ergebnis. Habe auch den Stack verdoppelt auf 0x1000 Byte(!), ohne Erfolg. Benutze einen LPC2148 mit 32+2 K RAM. Sind ca. 4K RAM belegt. Sollte eigentlich vorerst reichen. Danke und Gruss
Mach mal direkt am Anfang von PID_Controller(...) ne Abfrage für pid rein. z.B.:
1 | float PID_Controller( ...) { |
2 | if( !pid) { |
3 | // Fehlerausgabe
|
4 | }
|
5 | float .... |
6 | }
|
Wenn da kein Fehler kommt, dann liegts am Debugger. Vielleicht kennt er den Wert von pid noch nicht und nimmt deshalb NULL als Adresse. Einfach mal weiter unten in der Funktion nen Breakpoint setzen.
Danke Martin. Wäre ne Idee, aber ich weiss , dass es der Debugger nicht ist. Die PID_Controller Funktion wird nämlich nicht komplett durchlaufen, sondern endet etwas später in einem BUSERROR Trap. Dadurch habe ich es erst gemerkt, dass da was nicht stimmt. Habe deinen Vorschlag dennoch ausprobiert. Der Fehlerdurchlauf war wie erwartet da. Gruss
Sorry, wieder ein Bild. Habe mal bei Aufrufe testhalber von der Parameteranzahl gleich gemacht und den Assembler Code beider Aufrufe angezeigt. Aus irgend einem Grund sind beide Aufrufe total unterschiedlich umgesetzt. Einziger Unterschied beim Aufruf ist der eine gezeigte Parameter der nicht durch typedef union definiert ist. Gruss
Vergessen, da ändert sich auch nichts dran wenn die PID-Conntroller Funktion so umgebaut ist, dass sie nichts zurück liefert.
Im letzten Fall wird der zweite Parameter als "double" übergeben, im Thread liegt aber als Deklaration der Funktion (aus dem ersten Screenshot) nur eine Version vor, die dort "float" erwartet. Und das Resultat wird von "int" nach "float" konvertiert. Wie soll man damit was anfangen? Wie soll man den Assembler-Code eines Aufrufs bewerten, dessen aktuelle Deklaration man nicht kennt? Die Datentypen der Variablen ebensowenig.
Ich benutze hier (wissentlich) keine double. So sind die Variablen global declariert: typedef union _un_float_to_char { float fVal; u_char cVal[4]; }un_float_to_char; //--------------------------- float f_pid_tempdiff1_ist; float f_pid_tempdiff_ist; float f_pid_diff; float f_pid_solltempdiff; un_float_to_char f_p1_factor_set; un_float_to_char f_i1_factor_set; un_float_to_char f_d1_factor_set; un_float_to_char f_pid1_solltempdiff; struct PID_DATA tdr1_pid_struct; Reicht das ? Vielen Dank
Das Problem ist gelöst! Ich bekam einen Tip von einem Bekannten, der schon mal ein ähnliches Problem hatte. Er riet mir die PI-Controller Funktionen komplett zu kopieren und an einem anderen Ort mit anderem Namen nochmals zu platzieren und dann diese Funktion aufzurufen. Im zweiten Anlauf bekam ich dann die "erhofften" Fehlermeldungen des Compiler bezüglich der fVal bei den Parameteraufrufen. Und schon hat es funktioniert. Nach weitern Untersuchungen kam ich dann drauf, dass die ursprüngliche Funktion auch richtig arbeiten, wenn ich sie im "Hauptprogram" als extern deklariere. Das hatte ich wohl übersehen. Also mit anderen Worten, sind die PID_xxx Funktionen als extern nicht dekariern , mecckert der Compiler nicht , aber geht auch nicht. Sind die PI_xxx Funktionen als extern delariert, meckert der Compiler auch nicht (soll er auch nicht) , aber es funktioniert wie gewünscht. Danke Stefan für den sehr hilfreichen Tip. Danke auch an alle die sich Zeit für mein Problem genommen und versucht haben mir zu helfen. Gruss
> Also mit anderen Worten, sind die PID_xxx Funktionen als extern nicht > dekariern , mecckert der Compiler nicht , aber geht auch nicht. Der Compiler braucht den Funktionsprototypen, um zu wissen, dass die aufgerufene Funktion float-Argumente erwartet. Weiß er dies nicht, übergibt er die Argumente als double, was zur Laufzeit für Verwirrung sorgt. Mit der Option -Wimplicit warnt der Compiler vor fehlenden Prototypen, deswegen sollte diese Warnung für selbstgeschriebene Programme immer eingeschaltet sein. Noch besser ist es, -Wall anzugeben. Diese Option schließt -Wimplicit mit ein und warnt zusätzlichen vor vielen weiteren gefährlichen Konstrukten. Man erspart sich damit — wie auch in deinem Fall — viel Ärger für die Fehlersuche :)
Danke für den Hinweis, wußte ich natürlich nicht. Habe -Wall im Makefile eingebaut. Gruss
-Wall ist wirklich der Hammer! Da habe ich heute viel gelernt (und einige Zeit aufwenden müssen alles wieder gerade zu biegen)! Man sieht auch was der Compiler eigentlich so quasi tolleriert und implizit annimmt. Oft ist es ok, manchmal aber doch eher nicht. Man sieht weiter, dass manche Experten (paar SW-Teile habe ich mir ausgeliehen) es auch nicht so genau nehmen! Danke nochmals für den Tip. Gruss
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.