Ich habe mir für meine Codesammlung mal eine Frequenzmessung programmiert um später evtl. auch ein LC-Meter zu bauen. Ich programmiere grundsätzlich immer mit der Optimierung -O0. Das Programm funktioniert damit auch schon sehr gut. Nun habe ich mal die Optimierung auf -Os umgestellt, da ich ja die delay.h verwende und in der Hilfe zu der lib steht, dass man unbedingt die Codeoptimierung einschalten soll. Nun hab ich aber das Problem, dass mein Programm nicht mehr funktioniert, also wird irgend etwas wegoptimiert, was ich eigentlich bräuchte. Da denk ich mir, stellen wir die Optimierung eben wieder auf -O0, aber das Programm läuft immer noch nicht!?!?! Kann mir das einer erklären? Ich bin froh, dass ich zufällig noch ein BackUp auf dem Stick hatte.
Ach so, ich bin leider nicht zu Hause - kann also nicht genau sagen welche Version ich von AVR Studio (irgend eine 4.x Version) bzw von WinAVR (irgend was von 2007) nutze. Das Programm läuft auf einem ATMega32 mit 16Mhz Quarz.
Was funktioniert nicht? Läuft gar nichts? BTW: Bist Du sicher, dass die Zahlen hier
1 | zeitdiff=(65535-zeit1)+65635*(ueberlauf-1)+zeit2; |
stimmen? Zumindest die zweite Zahl würde ich instinktiv anzweifeln...
Ich bekomme nach der Optimierung einfach keine Anzeige auf dem Display. In
1 | zeitdiff=(65535-zeit1)+65635*(ueberlauf-1)+zeit2; |
ist natürlich die 2. Zahl falsch (Tippfeler^^, muss 65535 sein). Erklärt aber immer noch nicht das Problem mit der Optimierung, da der Schreibfehler ja nur eine konstante Abweichung der Frequnz hervorrufen sollte. Mein "Gedankengang" zu der Codezeile steht als Kommentar auch darüber, falls du es nachvollziehen möchtest. Trotzdem schon mal dickes DANKE für die Entdeckung des Tippfehlers ;) Würde mich freuen wenn noch mehr Vorschläge zur Verbesserung meines Codes kommen. Man lernt ja nie aus und gerade bei Frequenzmessung kommt es auf sauberen Code an um genaue Messungen durchführen zu können.
Nun, da ich die lcd.h (und die vermutlich dazugehörige lcd.c) nicht kenne, kann ich dazu nix sagen...
>zeitdiff=(65535-zeit1)+65635*(ueberlauf-1)+zeit2;
Und wenn du eine der Variablen nach unsigned long castest, damit die
ganze Rechnung in long ausgeführt wird? So rechnet der µC ja nur in
unsigned int. Kann es da zu Überläufen kommen?
MW
Michael Wilhelm wrote: > du eine der Variablen nach unsigned long castest, damit die > ganze Rechnung in long ausgeführt wird? So rechnet der µC ja nur in > unsigned int. Kann es da zu Überläufen kommen? Das würde aber auch ohne Optimierung passieren...
Die LCD Routinen sind von Peter Fleury aus der HD44780U LCD library.
>>zeitdiff=(65535-zeit1)+65635*(ueberlauf-1)+zeit2; > > Und wenn du eine der Variablen nach unsigned long castest, damit die > ganze Rechnung in long ausgeführt wird? So rechnet der µC ja nur in > unsigned int. Nein. So wie es oben steht, wird das in long gerechnet.
Ach ja, was ich vergaß:
1 | zeitdiff=(65535-zeit1)+65535*(ueberlauf-1)+zeit2; |
2 | //umgestellt--> zeitdiff=65635*ueberlauf+zeit2-zeit1;
|
Wieso schreibst du die einfachere Formel in den Kommentar statt direkt in den Code?
OK, wenn ich Glück habe, liegt es nur an der LCD libery. Kann ja sein, dass da delay Pausen drin sind welche für mein Display zu kurz sind (ohne Optimierung sind die delays ja zu groß und könnten so gerade passen). Ich probier das heute Abend mal mit einer simplen LCD Ausgabe aus und sag dann morgen bescheid. Die einfache Formel steht im Kommentar, weil ich das erst nachträglich geändert habe und noch nicht getestet ist. Quasi als Gedankenstutze, das ich das noch machen muss. Ich baue neuen Code immer erst nach dem Test ein - never change a running system. Ist der Code der Frequenzmessung ansonsten so OK, oder kann der noch verbessert werden (geht bestimmt^^).
Ich hab mir beim Mittag noch mal gedanken darüber gemacht. An der LCD Libery kanns ja eigentlich auch nicht liegen, da das Programm beim zurückzetzen de Optimierung auf -O0 auch nicht mehr funktioniert. Irgend einer ne Idee? Evtl. spinnt ja nur AVR Studio.
Timer wrote: > Ich hab mir beim Mittag noch mal gedanken darüber gemacht. An der LCD > Libery kanns ja eigentlich auch nicht liegen, da das Programm beim > zurückzetzen de Optimierung auf -O0 auch nicht mehr funktioniert. Wie jetzt? Dann ist die Optimierung also doch nicht Schuld? > Irgend einer ne Idee? Evtl. spinnt ja nur AVR Studio. AVRStudio hat damit nichts zu tun. AVRStudio kann kein C und hat mit dem Compilieren an sich nichts am Hut.
Ich hab im Ersten Beitrag geschrieben, dass ich -Os eingestellt habe und das Programm nicht mehr lief. Nach dem zurückstellen auf -O0 gings aber auch nicht mehr, obwohl der Code der gleiche geblieben ist. Nachdem ich das BackUp von meinem Stick gezogen hatte war alles wieder i.O. Bei jedem Versuch das gleiche Verhalten - keine Anzeige mehr auf dem Display. Will aber eigentlich schon die Optimierung reinnehmen, da es schon einen Unterschied macht ob das Programm 6500kB oder 1200kB verbraucht. Soll evtl. mal auf nen ATMega8 oder 2321.
Timer wrote: > Ich hab im Ersten Beitrag geschrieben, dass ich -Os eingestellt habe und > das Programm nicht mehr lief. Nach dem zurückstellen auf -O0 gings aber > auch nicht mehr, obwohl der Code der gleiche geblieben ist. EBEN. Das ist nämlich eigentlich so gut wie unmöglich.
Genau deswegen denk ich ja, dass es evtl. an AVR STudio (da stell ich ja die Optimierung ein) oder WinAVR liegt Ich kanns mir halt auch nicht erklären, deswegen frag ich ja ;)
Irgend etwas muss dir beim Einschalten der Optimierung noch passiert sein. Im Code sehe ich nichts was das von dir beschriebene Verhalten erklären könnte (*). Auch wenn ich manches anders machen würde, sehe ich eigentlich nicht, warum da keine Ausgabe aufs LCD mehr erfolgen sollte. (*) Stimmt nicht ganz. Ich würde nicht auf flanke_anz == 13 abfragen, sondern auf größer. Wenn dein Programm aus irgend einem Grund die 13.te Flanke verpasst dann kannst du das mit einem > immer noch abfangen. Wenn die Variable aber exakt 13 sein muss, dann kannst du ev. ein Problem haben. Was ich an deiner Stelle jetzt tun würde: Den Behandlungscode in main() mal kürzen, so dass die Interrupts kürzer gesperrt sind.
1 | while(1) |
2 | {
|
3 | if (flanke_anz > 12) |
4 | {
|
5 | cli(); |
6 | |
7 | if (ueberlauf==0) |
8 | {
|
9 | zeitdiff=zeit2-zeit1; //wenn kein �berlauf dann nur zeit zwischen timestamp's |
10 | }
|
11 | else
|
12 | {
|
13 | //bsp f�r 2 �berlaufe:
|
14 | // t1 �1 �2 t2
|
15 | // ...|-----|-----------|---|...
|
16 | // 65535-zeit1 zeit2
|
17 | // 65635*(ueberlauf-1)
|
18 | zeitdiff = (65535-zeit1) + 65535 * (ueberlauf-1) + zeit2; |
19 | //umgestellt--> zeitdiff=65635*ueberlauf+zeit2-zeit1;
|
20 | //wenn �berlauf, dann zeit von 1.timestamp zu 1.�berlauf +zeit f�r alle �berl�ufe +zeit von letztem �berlauf bis 2.timestamp
|
21 | }
|
22 | |
23 | ueberlauf=0; //�berl�ufe f�r n�chste Messung r�cksetzen |
24 | flanke_anz=0; //R�cksetzen f�r n�chste Messung |
25 | sei(); |
26 | |
27 | ltoa( zeitdiff, s, 10 ); |
28 | lcd_clrscr(); |
29 | lcd_puts( zeitdiff ); |
30 | |
31 | //lcd_puts("/n");
|
32 | //frequenz=cpu_takt/zeitdiff;
|
33 | //lcd_puts(dtostrf(frequenz,6,3,s));
|
34 | }
|
35 | }
|
von Karl heinz Buchegger: "Was ich an deiner Stelle jetzt tun würde: Den Behandlungscode in main() mal kürzen, so dass die Interrupts kürzer gesperrt sind." Ist es denn schlimm wenn die Interrupts längere Zeit gesperrt sind? Gut, ich erhalte keine Messdaten, aber sobald ich die Interrupts wieder einschalte sollte doch alles wieder von vorne laufen.
> Ist es denn schlimm wenn die Interrupts längere Zeit gesperrt sind? Naja, ist eben so eine Grundregel, die Interrupts nie länger als absolut nötig zu sperren. > Gut, ich erhalte keine Messdaten, aber sobald ich die Interrupts wieder > einschalte sollte doch alles wieder von vorne laufen. Es werden zumindest mit guter Wahrscheinlichkeit die Interrupt-Flags deiner beiden Interrupts gesetzt sein, so daß sofort nach dem sei() erstmal irgendwelche alten Interrupts von "früher" deine beiden ISRs auslösen werden.
"Es werden zumindest mit guter Wahrscheinlichkeit die Interrupt-Flags deiner beiden Interrupts gesetzt sein, so daß sofort nach dem sei() erstmal irgendwelche alten Interrupts von "früher" deine beiden ISRs auslösen werden." genau deswegen verwerfe ich auch die erstn 2 Flanken und fange erst mit der 3. an über 10T zu messen Kann man die Interruppt-Flags denn nicht löschen bzw. kommen die überhaupt wenn Interrupts deaktiviert sind? Das wäre ja sonst ein grundsätzliches Problem. Ich mache meine Interrupt Routinen immer extra klein, da der nächste Interrupt mir ja im Nacken hängt. Den Hauptteil von Berechnungen und Co. mache ich deswegen immer in der main und stelle vorher die Interruts ab, damit ich Zeit zur Rechnung habe. Ist das jetzt doch nicht so günstig?
Timer wrote: > Kann man die Interruppt-Flags denn nicht löschen bzw. kommen die > überhaupt wenn Interrupts deaktiviert sind? Natürlich "kommen" die auch, wenn die Interrupts nicht freigegeben sind. Sonst könnte man kein Polling machen. Und natürlich kann man die auch von Hand löschen (von wenigen Ausnahmen abgesehen).
OK, ich hab mir mal eine einfache Display Routine geschrieben und Os eingestellt, hat funktioniert Dann hab ich mal ein Blinklicht gemacht mit O0 funktionierts mit Os geht das Display nicht, aber die LED's blinken. Wenn ich wieder auf O0 zurückgehe geht das display auch nicht mehr aber die LED's blinken, klingt komisch, ist aber so Dann hab ich mal mit dem Interrupt rumprobiert. hab einfach den int0 genommen. Mit O0 funktionierts mit Os nicht und wenn ich wieder auf O0 zurückgehe gehts auch nicht mehr. Diesmal hab ich aber die hex dateien zwischengespeichert und siehe da, beim ersten mal mit O0 sind einige hex werte geändert als beim 2. mal O0 nach Os??????? Irgend was läuft das schief. Ach so, meist wird die LCD init und das clr noch gemacht, zumindest zeigt das Display keine "schwarzen Quadrate"
Hast du nach den Änderungen immer wirklich alles neu übersetzt? Wenn du im Makefile die Optimierungseinstellungen änderst, wird nicht automatisch alles neu gebaut.
Wie und wo stellst du denn die Optimierungsstufen ein? In den AVRStudio-Projektoptionen, oder woanders? Oliver
Nachtrag: Vergleiche doch auch mal den Konsolenoutput von Compiler und Linker, ob da bei den Läufen mit -O0 irgendetwas unterschiedlich ist. Am besten in externe Textfiles kopieren, und mit Winmerge o.ä. ansehen. Oliver
Die Optimierungsstufen stell ich direkt bei AVR Studio ein. Ich hab kein extra makefile, sondern stell unter Projekt Options (oder so ähnlich) meinen ATMEga32, die 16MHz und halt die Optimierung ein. Dann bekomm ich mein *.hex file und "brenne" dann mit PonyProg mein ATMega32. Habe jetzt kein AVR Studio zur Hand, aber zum Übersetzen nehme ich immer den linken der beiden Compilebuttons. Sollte auch so stimmen, denn von der Einstellung -O0 nach -Os wird ja auch alles neu Übersetzt, da sollte es umgekehrt ja genauso sein. Konsolenoutput werd ich heut Abend mal anschauen.
Achte doch einfach mal darauf, welche Uhrzeit deine Hex hat. nicht das du die ganze zeit eine "andere" hex lädst...
>Mit O0 funktionierts mit Os nicht und wenn ich wieder auf O0 zurückgehe >gehts auch nicht mehr. Diesmal hab ich aber die hex dateien >zwischengespeichert und siehe da, beim ersten mal mit O0 sind einige hex >werte geändert als beim 2. mal O0 nach Os??????? @Werner, also 3 verschienene *.hex Dateien. Die erste mit O0 geht die zweite mit Os nicht und die dritte wieder auf O0 eben komischer weise auch nicht
Hallo, nur mal wegen des Effekts, daß das Display auch mit -O0 dann nicht mehr geht: Spannung mal ganz aus und wieder ein? Das Display wird abgestürzt sein, das bekommt ja keinerlei Reset und verbleibt vermutlich in einem undefinierten Zustand nach dem Zugriff mit den falschen Timings bei -Os. Gruß aus Berlin Michael
Die Sache mit der Spannung war mein erster Gedanke. Hat aber nicht geklappt.
very strange, das alles. Wenn die hex-Dateien der beiden -O0-"Versionen" unterschiedlich sind, gibt es auch Unterschiede in den .lss, .map, oder anderen Dateien? Und wenn ja, welche? Welche WinAVR-Version, welche Studio-Version (da der Consolenoutput keine size anzeigt, muß das alles ja schon was älter sein) Schon mal mit frisch installierten, und/oder aktuelleren Versionen probiert? Oliver
Ich hatte erst alles mir den neuen Versionen probiert, hab dann gedacht, dass es daran liegt und meine alten Versionen (AVR Studio 4.12, WinAVR von 01.2007) wieder installiert, aber war genauso. Zu der Zeit hab ich dann auch die Konsolenoutputs gemacht.
Hallo ich arbeite auch mit dem AVR Studio und nutze winavr über das GCC Plugin. Was sein kann das du nach dem zurückstellen ur -O0 nur ein Teil der Objekt Files neu Compiliert wurden und somit avr-gcc da einfach nurks macht. hilft eigentlich dann meistens wenn du dann über Build -> ein mal Clean sagst und dann klick ich immer Rebuild All an. Sollte eventuell helfen. Hat mich zumindest auch hinundwieder nerfen gekostet. MfG Kai
Hallo Kai, > hilft eigentlich dann meistens wenn du dann über Build -> ein mal Clean > sagst und dann klick ich immer Rebuild All an. Sollte eventuell helfen. danke für diesen wertvollen Tipp -- nach einigem Haareraufen mit einem ähnlichen Problem wie von "Timer" oben beschrieben hat er mich gerettet! Gruß Fred
> hilft eigentlich dann meistens wenn du dann über Build -> ein mal Clean > sagst und dann klick ich immer Rebuild All an. Sollte eventuell helfen. Wobei das Studio eigentlich sehr zuverlässig in der Bestimmung der dependencies ist. Wenn das Projekt mit allen benötigten Sourcen richtig angelegt ist, dürfte da nichts schiefgehen. Oliver
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.