Hallo zusammen.. Seit geraumer Zeit versuche ich eine Zeitmessung im Auto von 0 auf 100 zu programmieren. Es hat auch schon geklappt. Nun bin ich (um ADC und TWI fertig zu haben) auf den MEGA8535 umgestiegen und habe dabei auch gleich den Takt auf 8MHz angehoben, Timer umgestellt usw.. Auf jeden Fall funktioniert das nichtmehr! Ich nutze den Timer/Counter2 um alle 2ms einen interrupt zu starten. Mit diesem Interrupt habe ich schon eine Uhr programmiert, welche im Rahmen der Genauigkeit(1s auf 40min falsch) lief. Also ist mit dem Interrupt alles richtig. Jetzt habe alles andere Funktionen rausgeschmissen und im Interrupt SIGNAL(SIG_OUTPUT_COMPARE2) { if((kmh>0)&&(kmh<101)){zeit2ms_mess++;} } gelassen. Im Hauptprogramm läuft noch eine Endlosschleife, welche mir die zeit2ms_mess im format XX,XXSEK ausgibt. siehe Quellcode Wenn ich nun an meinem Signaleingang Impulse gebe komme ich auf maximal 20kmh. Also müßte die Ausgabe zählen, wenn ich aufhöre stehen bleiben und dann wieder zählen, wenn ich Impulse geb. Es zählt aber bis 00,35SEK und bleibt dort, wenn ich aufhöre Impulse zu geben, gehts wieder auf 0 zurück.. Der angehängte Quellcode enthält natürlcih noch viel unnützes und macht manche Sachen vielleicht nicht ganz sauber. Das kommt halt daher, daß ich alles rausgeschmissen habe und jetzt schon eine Weile daran ohne Erfolg rumdoktor.. Prinzipiell müßte es aber doch so funktionieren, Wenigstens die Zeit zählen Ich hoffe jemand kann mir da weiterhelfen, bin da so langsam am verzweifeln! Vielen Dank Jens
Hallo Jens, ist eigentlich ganz einfach, ist nämlich das FAQ-Topic #1 (tschuldige, ist aber nun mal so). Du mußt die variable zeit2ms_mess als "volatile" deklarieren. Also so: volatile unsigned int zeit2ms_mess; Nur so weiß der AVR-GCC daß diese Variable auch außerhalb des normalen Programmablaufs (zB im Interrupt) verändert werden kann. Dies gilt natürlich auch für alle anderen Variablen die Du zB in den Interrupts verwendest. Was sonst noch fehlt, ist das Handling drumherum, aber vielleicht hattest Du das einfach auch zur Vereinfachung entfernt. Wie zB. - Nach einer Messung auf Null setzen - Derzeit zählt er weiter wenn Du wieder unter 101km/h kommst - ... Volkmar
Danke für die Antwort aber mit volatile habe ich es gerade geteset und es ist das gleiche Scheißspiel.. Bis 350ms (00,35SEK) und dann wieder abwärts.. Dann müßte die Uhr(die den gleichen 2ms timer nutzte), kmh-Zahl und die impulzahlen bzw gefahrenen kilometern eigentlich auch nicht funktionieren? Die werden aber alle sauber dargestellt! Hab ehrlich gesagt noch nie etwas mit volatile deklariert.. Ja das handling habe ich jetzt mehrmals verändert und hat mit der damals funktionierenden fast nichtsmehr gemeinsam. Wenn er nichtmal bis 351ms zählt kann man sowas schlecht testen und es macht auch keinen Spass jedesmal alles komplett durchzudenken.
ok, das Programm oben kann so nicht funktionieren, weil das obligatorische strcpy(ausgabe,""); am Anfang fehlt und der string immer länger wird, das display aber nur die ersten 8 zeichen ausgibt... ich habe alle variablen volatile gemacht. Im aufteilen(..) auch ein unsigned int genommen usw.. hat alles nichts gebracht.. Erst das umbenennen der "zeit2ms_mess" variable in "s" im editor durch finden und ersetzen hat die geschichte zum laufen gebracht!! Zumindest auf dem Schreibtisch mal.. Meine Uhrvariable heisst zeit2ms_trip und die läuft doch auch? Kann mir jetzt bitte einer erklären warum das so ist.. gruss Jens
Wundert mich jetzt auch, daß es mit den anderen Variablen funktioniert. Eventuell hängt es mit der eingestellten Optimierung zusammen. Aber das Du die Variable umbenennen musstest, wundert mich schon. Da kann ich Dir wohl auch nicht weiterhelfen. Volkmar
So, jetzt bin ich ein bischen Probe gefahren und schon gibs die nächsten Absonderheiten: im interrupt von der kmh berechnung steht if(kmh>maxkmh){maxkmh=kmh;} Ansonsten mache ich nichts mit dem maxkmh außer halt ausgeben.. Im Auto zeigt mir maxkmh aber selstamerweise die aktuelle Geschwindigkeit an, also als ob die if schleife nicht gilt und gleich maxkmh=kmh gemacht würde. Genauso speichert er die bestzeit im 0 auf 100 rennen nicht richtig ab. der code: if(zeit_0100<bestzeit_0100){bestzeit_0100=zeit_0100;zeittemp=205;} Also er zeigt an, daß ich eine neue Bestzeit gefahren bin (das bedeutet das zeittemp=205), aber speichert diese offensichtlich nicht ab.. Alle Variablen als volatile. Gibt es da wirklich eine compiler option, die sowas so brutal wegoptimiert? Mit opt=3 oder s oder gar 0 funktionuckelt es allerdings auch nicht.Habe meine makefile sicherheitshalber angefügt. Ich blick das echt nicht. Ist bestimmt irgendein saudummer Fehler.. Bitte sagts mir, verlier langsam echt die Lust hier.. gruss Jens
Also ich habe wieder maxkmh in mkmh umbenannt (replace) und siehe da, es tut was es tun soll! Das mit der Bestzeit kann ich nicht testen, weil ich noch nicht im Auto damit war. Ich habe den Eindruck das der Atmel die Variable automatisch wieder auf 0 zurückgesetzt hat. Also das die if schleife schon greift, aber maxkmh eben immer automatisch abgefallen ist, so wie die 350ms auch von allein wieder auf 0 ist, obwohl sie hätten stehen bleiben müssen?! Habe WinAVR 20040404, also auch das neuste, im AVR libc z.B. steht der atmega8535 als [untested].. Kann es sein, daß es deswegen zu Problemen kommen kann und ich einfach auf ein neues update warten muß? Oder habe ich ein Virus im Atmel ;) Hat wirklich keiner irgendeine Idee, warum das so ist? gruss Jens
Die Anmerkung "atmega8535 [untested]" kann in dieser Hinsicht eigentlich keine Auswirkung haben. Mich wundert schon, daß eine Umbenennung der Variablen es zum Funktionieren bringt. Ich hatte da bisher keine Probleme. Scheint mir so, als ob es einen Namenskonflikt gibt. Ist aber nur eine Vermutung. Volkmar
Also der Fehler ist auch wirklich reproduzierbar! ich habe das gleiche Programm einmal mit maxkmh kompiliert und dann mit mkmh! Die Version mit mkmh funktioniert, die mit maxkmh nicht. Auch wenn ich von mkmh wieder in maxkmh umbenenne, funktioniert es wieder nicht. Wenn ich die .lss Dateien anschauen, sind die exakt gleich groß. Beide scheinen auch alles gleich zu machen. Der einzige Unterschied, der mir aufgefallen ist, war, daß die Variablen eben in anderen Adressen standen. Beim funktionierenden: mkmh: 0x0216 0x0215 dabei kmh in 0x0209 und 0x020A beim nicht funktionierenden: maxkmh:0x020A 0x0209 dabei kmh in 0x020C 0x020B Die Adressen werden aber nur benutzt, wenn wirklich maxkmh gebrauch/verändert wird. Also da pfuscht nichts zwischendrin mal rein. (soweit ich diese vielen Zeilen assembler überblicken kann) Gibt es beim mega8535 evtl irgendwelche Besonderheiten, die ich beachten müßte? Ich hoffe damit kann jemand etwas anfangen ;) gruss Jens Peter (hier gibs soviele Jens hab ich gemerkt)
Servus.. Also um das aufzuklären. der string ausgabe[] wurde im Programm größer als geplant, so daß es die Variable, welche im Speicher direkt nach dem string liegt überschreibt. So kamen dann halt irgendwo Phantasiewerte rein.. Ich hoffe das wars jetzt wirklich ;) Vielen Dank nochmal an Volkmar ohne den ich diesen Fehler wohl noch ewig gesucht hätte!!!
Du solltest nur sichere Funktionen verwenden, also fgets statt fget calloc statt malloc strncat statt strcat strncpy statt strcpy snprintf statt sprintf strncmp statt strcmp vsnprintf statt vprintf dann gibt't nämlich auch weniger exploits. In ein Prettyprinting-Skript habe ich deshalb Warnungen eingebaut, die warnen, wenn eine der kritischen Funktionen im Sourcecode ist.
Naja, "it depends". Gerade bei Controllern kommt es schnell mal auf die verfügbaren Ressourcen (Codegröße, Rechenzeit) an, so daß ich diesen Hinweis nicht allgemein stehen lassen würde. Wenn ich mir einen Puffer mit malloc() geben lasse, den ich anschließend fülle, warum soll ich ihn vorher von calloc() noch plattmachen lassen? Ist doch schade um die Arbeit, wenn danach das Ergebnis von calloc() zunichte gemacht wird. calloc() als lame excuse, sein Stringende nicht ordentlich abzuschließen, würde ich ohnehin nicht unterstützen wollen. Das hieße ja, schlampige Programmierung nur durch andere Methoden zu flicken, statt sie gleich gar nicht erst schlampig werden zu lassen. Gleiches gilt für die diversen str* Funktionen ohne `n' drin: wenn man weiß, was man tut, kann man die auch nehmen. strlcat/strlcpy sind zuweilen ohnehin ein besserer Ersatz als strncat/strncpy. Einzig der Benutzung von fgets() statt gets() würde ich uneingeschränkt zustimmen, da man die mögliche Fehlersituation bei gets() aufgrund seines Lesens von stdin fast nie unter Kontrolle bekommen kann.
Also malloc wird sehr selten auf MCs verwendet; da sollte calloc statt malloc nur wirklich keinen nennenswerten Unterschied machen. Außerdem bekommt man durch calloc eine Initialisierung und nicht nullterminierte strings bekommt man dadurch (sofern die vor dem allozierten Bereichsende enden) nullterminiert. Wenn man ein paar Funktionen nimmt, die einige Fehler beseitigen oder limitieren, bringt das schon etwas. Schließlich gibt's Fehler ja nicht nur in der Implementation sondern auch in Hardware und der Spezifikation. Deshalb überprüfe ich beispielsweise in einer Warteschleife nicht ob der Endwert erreicht wurde, sondern ob der Wert größer gleich dem Endwert ist.
> Also malloc wird sehr selten auf MCs verwendet; da sollte calloc > statt malloc nur wirklich keinen nennenswerten Unterschied machen. Ah, Du kennst Dich aus. Interessant. > Außerdem bekommt man durch calloc eine Initialisierung und nicht > nullterminierte strings bekommt man dadurch (sofern die vor dem > allozierten Bereichsende enden) nullterminiert. Genau gegen diese Variante schlampiger ,,ganz genau weiß ich auch nicht, wo mein String zu Ende ist, aber calloc() wird's schon richten'' Programmierung habe ich mich oben gewandt. Die kaschiert letztlich nur die Bugs des Programmierers. Aber da Du Dir nicht mal 'nen Namen leisten kannst, ist das für mich EOD.
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.