Hallo Leute. Folgender Code streikt bei mir: #include <avr/io.h> volatile unsigned char test=0;; void main (void) { while(1) { switch(test) { case 0: test++; if (test>2) test=0; break; case 1: test++; if (test>2) test=0; break; case 2: test++; if (test>2) test=0; break; } } } bei jedem schleifendurchgang müsste er einen anderen case zweig nehmen. Aber obwohl test null ist hüpft er beim ersten mal laut avr studio simulation sofort in den case 2 zweig..... Warum...???!!!!!!! bitte um eure antworten
Hallo, an Deinem Code wird es sicher nicht liegen. Dieser Code funktioniert bei mir:
1 | #include <cstdlib> |
2 | #include <iostream> |
3 | #include <windows.h> // wegen Sleep(DWORD) |
4 | |
5 | using namespace std; |
6 | |
7 | |
8 | unsigned char test; |
9 | |
10 | int main(int argc, char *argv[]) |
11 | { |
12 | test = 0; |
13 | |
14 | for (;;) |
15 | { |
16 | cout << (unsigned int)test << "\n"; |
17 | |
18 | switch( test ) |
19 | { |
20 | case 0: |
21 | test++; |
22 | break; |
23 | case 1: |
24 | test++; |
25 | break; |
26 | case 2: |
27 | test = 0; |
28 | break; |
29 | } |
30 | |
31 | Sleep( 500 ); |
32 | } |
33 | |
34 | system("PAUSE"); |
35 | return EXIT_SUCCESS; |
36 | } |
Dieser Code ist geschrieben in Dev-Cpp unter Windows. AVR Studio habe ich leider nur mit Assemblerunterstützung, ich kann nicht weiterhelfen. Gruß, Feadi
Schalt mal die Compileroptimierungen ab. Der Compiler sieht nämlich überhaupt keinen Sinn darin (und ich auch nicht) für jeden case-Zweig seperaten Code zu erzeugen, wenn alle Zweige identisch sind.
Schalt mal die Compileroptimierungen ab. Der Compiler sieht nämlich überhaupt keinen Sinn darin (und ich auch nicht) für jeden case-Zweig seperaten Code zu erzeugen, wenn alle Zweige identisch sind. Das ist jetzt nur ein beispiel. Ich habe schon einen größeren Code mit unterschiedlichen Case blöcken. Hab mich jetzt nur aufs herunterste getestet und nichtmal das funktioniert. die 2 semikolons machen nicht hab ich schon getestet. Wie schaltet man die Compileropt ab?
Anders gesagt: benutze keine degenerierten Testfälle. Du kannst einem Compiler, der Projekte von 100000 Quellzeilen locker in der Praxis bewältigt, ruhig glauben, dass er compilieren kann. Denk dir also lieber etwas aus, was auch wirklich irgendwie sinnvollen Code erzeugt, und gib dem Compiler das dann zum Compilieren hin.
> Das ist jetzt nur ein beispiel. > > Ich habe schon einen größeren Code mit unterschiedlichen Case > blöcken. Und das kann jetzt einer von uns riechen oder wie? > Hab mich jetzt nur aufs herunterste getestet und nichtmal das > funktioniert. Das funktioniert perfekt. Das einzige was nicht funktioniert ist der Programmierer der den Testfall gebaut hat. > Wie schaltet man die Compileropt ab? Menüpunkt Project / Configuration Options Allerdings: Eine Menge Leute die viel von Compilerbau verstehen haben eine Menge Hirnschmalz in diesen Compiler gesteckt. Die Wahrscheinlichkeit das du einen Compilerfehler entdeckt hast ist verschwindend gering. Sehr viel wahrscheinlicher ist es, dass dein Programm (das richtige, nicht der Testfall!) einen Fehler enthält.
@Karl Heinz Buchegger Bitte ordentlich Comments die helfen. Naja Compilerfehler. Entweder hat mein makefile einen fehler oder das winavr kompiliert die elf datei nicht richtig. Also ich schreibe den Code mit dem Programmers Notepad und kompiliere ihn dort auch. über avr studio tu ich dann debuggen (simulieren). Wenn ich den Code mit AVR Studio schreibe und mit AVR studio builde (ohne makefile) dann funktionert das simulieren. Sobald ich im AVR Studio einstelle das er ein makefile verwenden soll funktioniert das simulieren nicht mehr richtig. makefile habe ich mal angehängt. Andere frage: Ich habe im Projectverzeichnis vom AVR-Studio meine Sourcefiles. Wenn ich diese alle einbinden will: mit #include <beispiel.c> kommt die fehlermeldung das er das file nicht findet. Wie kann man dem dummen AVR studio relative pfade angeben? schöne Grüße
> Sobald ich im AVR Studio einstelle das er ein makefile verwenden > soll funktioniert das simulieren nicht mehr richtig. Kann ich mir nicht vorstellen. Was soll den der Simulator damit zu tun haben ob du ein externes Makefiole benutzt? In dem Moment in dem der Simulator loslegt, ist das Makefile aber sowas von unintereessant. > makefile habe ich mal angehängt. Da ist ja immer noch die Optimierung aufgedreht! Bist du lernresistent? Schalt die Optimierung ab!
> Entweder hat mein makefile einen fehler oder das winavr > kompiliert die elf datei nicht richtig. Oder du erwartest Dinge, die der Compiler dir nicht geben will. Der Compiler ist darauf getrimmt, praxistauglich möglichst guten Code zu erzeugen. Typischerweise beißt sich das mit der Anforderung vor allem beginnender Programmierer, jeden einzelnen Schritt ihres C-Codes auch tatsächlich in der Maschine wiederzu- finden. Der Compiler wird bestimmte Zwischenergebnisse, die du für dein Verständnis brauchst, eventuell am Ende gar nicht benötigen und sie daher eliminieren. Variablen wird er auch nur so lange Speicherplatz (im RAM oder in einem Register) gönnen, wie deren Ergebnis wirklich noch benötigt wird, danach kann er diese wertvolle Resource anderweitig benutzen. Das hat eben auch zur Folge, dass Variablen, die gar nicht benutzt werden (also zwar geschrieben aber nie gelesen) auch gar nicht erst existieren. Durch Ausschalten der Optimierung kannst du den Compiler dazu bewegen, den Code genau so zu erzeugen, wie du das hingeschrieben hast. Praxistauglich ist das aber nicht, und wenn dieser Code dann funktioniert, heißt das noch lange nicht, dass der optimierte Code trotzdem auch noch funktionieren muss.
> Ich habe im Projectverzeichnis vom AVR-Studio meine Sourcefiles. > Wenn ich diese alle einbinden will: > mit #include <beispiel.c> kommt die fehlermeldung das er das file > nicht findet. Das macht man auch nicht per include. Du klickst links im Projektbaum den Eintrag 'Source Files' an. Rechte Maustaste - 'Add existing Source file(s)' und zeigst ihm alle c Dateien, die zu dem Projekt gehören. > dem dummen AVR studio Wer im Glashaus sitzt, ....
>>Kann ich mir nicht vorstellen. Was soll den der Simulator >>damit zu tun haben ob du ein externes Makefiole benutzt? >>In dem Moment in dem der Simulator loslegt, ist das Makefile >>aber sowas von unintereessant. Warum kannst du dir das nicht vorstellen. Wenn ich bei meinem Project im AVR Studio einstelle das er das makefile verwenden soll dann funktiniert das debuggen nicht richtig. Wenn ich ohne makefile builde, sozusagen AVR studio simuliert durch die daten die ich in der gui angebe das makefile dann funkioniert es.
> dem dummen AVR studio >>Wer im Glashaus sitzt, .... Wenn man mit dem Visual Studio programmiert und dann macht man wieder mal was im AVR Studio dann geht einem das schnell auf den sack. Ich glaube man wird einfach zu bequem. greets
> Visual Studio Du benutzt Visual Studio und findest nicht alleine raus wie man Source Code Files zu einem Projekt hinzufügt? Das funktionert im Visual Studio völlig gleich! > dann funktiniert das debuggen nicht richtig. Bis jetzt hab ich nur Bedienerfehler, bzw. falsche Einstellungen bzw. falsche Erwartungen von dir gesehen. Da war aber auch rein gar nichts dabei, was den Schluss zulässt dass der Debugger nicht richtig funktioniert. Als Trost für dich: Es gibt tatsächlich Fehler im Simulator, aber das was du beschreibst ist definitv keiner. Alles funktioniert genau so wie man es erwarten würde.
>Als Trost für dich: Es gibt tatsächlich Fehler im Simulator, aber >das was du beschreibst ist definitv keiner. Alles funktioniert >genau so wie man es erwarten würde Achja. Wenn ich eine Switch case mache und die variable beinhaltet eine 1 und dann hüpft er in den case teil 5 das ist richtig ok.. vieleicht sollte ich die variable rückwärtszählen dann noch 3 mal verodern und noch einmal invertieren das es hinhaut.. danke für die hilfe..
> Visual Studio >>Du benutzt Visual Studio und findest nicht alleine raus >>wie man Source Code Files zu einem Projekt hinzufügt? >>Das funktionert im Visual Studio völlig gleich! Ich habe im WINAVR auch die Sourcefiles in meinem Project und da muss ich sie auch includen sonst geht nichts.
Vielleicht solltest du einfach mal lernen mit deinen Werkzeugen ukmzugehen. Mach mal dein ach so heiss geliebtes Makefile mit dem Programmers Notepad auf. Dann scrollst du ein bischen runter, bis du folgenden Abschnitt siehst: # Optimization level, can be [0, 1, 2, 3, s]. # 0 = turn off optimization. s = optimize for size. # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) Und was steht dort als Optimierungslevel? OPT = s s ! nicht 0 ! Du erlaubst also dem Compiler, dass er den Code umstellen darf, solange sich an der Programmlogik nichts aendert und der Compiler Bytes einsparen kann. Und genau das macht der Compiler auch. Und genau das siehst du auch im Debugger.
Wie wärs denn mit unterschiedlichen Anweisungen in den Zweigen? Dann hätte dein Programm auch einen Grund das auszuführen. Hast du dir das Ergebnis denn mal im Assembler angeschaut? Das geht doch beim Studio? Ausserdem benutzt du kein default. Hab ich mir persönlich angewöhnt is besser um Fehler zu finden. Marcus
> Wenn ich eine Switch case mache und die variable beinhaltet eine 1 > und dann hüpft er in den case teil 5 das ist richtig ok.. Kann ich so nicht beurteilen. In dem von dir geposteten Beispiel ist es ok. Weder du noch dein Programm kann den Unterschied feststellen solange du nicht im Debugger durchstepst. Und genau das darf der Compiler: Er darf dein Programm umstellen, solange sich das externe Verhalten nicht verändert. Im von dir geposteten Beispiel ändert sich rein gar nichts. > > vieleicht sollte ich die variable rückwärtszählen dann noch 3 mal > verodern und noch einmal invertieren das es hinhaut.. Den Sarkasmus kannst du dir sparen, der steht dir nicht zu. Nicht bei deinem Wissen.
>>Wie wärs denn mit unterschiedlichen Anweisungen in den Zweigen? Dann >>hätte dein Programm auch einen Grund das auszuführen. Hast du dir >>das >>Ergebnis denn mal im Assembler angeschaut? Das geht doch beim >>Studio? >>Ausserdem benutzt du kein default. Hab ich mir persönlich angewöhnt >>is >>besser um Fehler zu finden. Marcus if (chColor) { switch (Colorstep) { case 1: BLUE++; if (BLUE==MAX) Colorstep++; break; case 2: RED--; if (RED==MIN) Colorstep++; break; case 3: GREEN++; if (GREEN==MAX) Colorstep++; break; case 4: BLUE++; if (BLUE==MAX) Colorstep++; break; case 5: RED++; if (RED==MAX) Colorstep++; break; case 6: GREEN--; if (GREEN==MIN) Colorstep++; break; } chColor=0; So sieht meine switch case syntax aus. ich verstehe nicht warum er in case 5 springt wenn er eigenlicht in case1 springen sollte.
Ist aus diesem kurzen Ausschnitt nicht wirklich ablesbar. Bau mal daraus ein komplettes Programm, stell sicher, dass es immer noch den Effekt zeigt und stell es hier rein. In diesem Abschnitt ist nichts erkennbar, was diesen Effekt erklären könnte. Also muss es an den Teilen liegen die du nicht gezeigt hast. Daher die Bitte um kompletten Code. Insofern war dein Einstiegsposting absolut vorbildlich, nur hast du einen Fehler gemacht: Dein Testprogramm hat das Problem nicht dupliziert. Hier sind die einzelnen case-s unterschiedlich, in deinem Testprogram sind sie es nicht. Und da hat dann der Optimizer zugeschlagen. Hier kann er das nicht (zumindest nicht in dem Ausschnitt den wir sehen). Irgendwo schlägt er aber zu, da bin ich mir ziemlich sicher. Wir muessen jetzt nur die Stelle finden wo er zuschlägt.
Bist du sicher, dass er den case 5 anspringt und nicht den case 4 ? case 1 und case 4 sind naemlich identisch.
Meine Glaskugel streikt heute leider. Ich weiss nicht ob das beim simulieren geht, aber mach mal einen Datachangebreakpoint auf die Variable Colorstep und schau ob sie irgendwo sonst geändert wird. Marcus
Hallo Karl-Heinz die letzten Posts hören sich eher wieder nach dir an. Wusste gar nicht, dass du so fuchsig werden kannst;). Marcus
Wenn ich was hasse dann das, wenn die Leute die Schuld auf ihre Werkzeuge schieben und das Ganze dann auch noch so richtig süffisant rüberbringen. Dabei kann jeder Hauptschüler sehen, dass sie mit ihrem Werkzeug einfach nicht umgehen können. Sicher, jeder muss mal anfangen. Du kennst mich lange genug um zu wissen das ich mit Anfängern kein Problem habe. Aber wie gesagt: Fehlendes Wissen mit einer Schuldzuweisung an die Toolchain zu kompensieren, und sich dann auch nichts sagen lassen, da ....
Ja das ist wahr, ich hab schon viele deiner Beiträge gelesen und auch viel "rausgeholt", deswegen konnt ich mir den Beitrag einfach nicht verkneifen. Bin gespannt ob er das Problem in den Griff bekommt. Die zwei identischen Cases sind mir auch aufgefallen. Ich denke man kann sich das Ergebnis so vorstellen abhängig von der Optimierung: case 1,4: do something break; deswegen ja auch die Frage nach dem Assembly. Marcus
> Bin gespannt ob er das Problem in den Griff bekommt
Das kriegen wir schon hin. Sobald wir das Problem bei uns
reproduzieren können haben wir was um damit zu arbeiten.
Warten wir mal ab ob es ein Missverständnis zwischen 4 und 5
war. Die einzelnen cases sehen sich sehr ähnlich. Das kann
schon mal passieren, dass man im Debugger in die falsche Zeile
rutscht. Das ist momentan meine favorisierte Theorie. So ein
'Ablesefehler' ist schnell gemacht und zusammen mit dem Optimizer
würde es das 'Problem' ohne zusätzliche Annahmen erklären.
So ich leg meine Ohren nun an Masse ich wünsch ein schönes WE Marcus
Guten morgen. Es haut jetzt hin. Es war wirklich diese Compileroptimierung. Ich glaube aber einen anderen Fehler im AVR Studio gefunden zu haben. Vieleicht kann das jemand mal ausprobieren. Und zwar im FAST-PWM Mode der Counter wird das COMPARE REGISTER immer erst beim MAX des Zähler registers upgedatet. Beim Counter0 wird das bei einem prescaler von 64 gemacht richtigerweise bei der simulation gemacht. Wenn ich aber sage: no perscaling dann wird das COMPARE REGISTER einfach irgendwie upgedated. Nicht bei jedem Zählvorgang sondern ca. bei jedem 10ten. Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling SOFORT!! upgedated. Entweder habe ich wieder mal müll gecoded oder der simulator hat wirklich einen fehler. Vl ist einer so nett und testet das mal. Hier mein Code: //Counter-Output-Compare-Registers #define RED OCR0A #define GREEN OCR0B #define BLUE OCR2B void main(void) { TCCR0B =(1<<CS00); //no prescaler for counter0 TCCR2B = (1<<CS20); // no precaler for counter2 TCCR0A = (1<<WGM01) | (1<<WGM00); //FastPWM-mode for Counter0 TCCR2A = (1<<WGM21) | (1<<WGM20); //FastPWM-mode for Counter2 for (int i=0; i<=500; i++) { RED++; } for (int i=0; i<=500; i++) { GREEN++; } for (int i=0; i<=500; i++) { BLUE++; } while(1); } Der Code ist jetzt bei beiden Countern mit no prescaling. Prescaler 64 für Counter 0 währe: TCCR0B = (1<<CS01) | (1<<CS00); //prescaler clk/64 Bitte um eure Comments:
> Wenn ich aber sage: no perscaling dann wird das COMPARE REGISTER > einfach irgendwie upgedated. Nicht bei jedem Zählvorgang sondern > ca. bei jedem 10ten. Na ja. 'irgendwie' ist übertrieben. Es passiert immer noch dann wenn der Zähler MAX erreicht hat. Der Unterschied ist nur, dass du bei einem Prescaler von 1 bei einem Druck auf F10 nicht einen Taktzyklus ausführst sondern ein C Statement. Und in diesem C- Statement passieren mehrere Dinge: zum einen wird RED geholt, erhöht und wieder zurückgeschrieben; zum anderen wird der Schleifenzähler erhöht. All das braucht von einmal F10 zum nächsten ein paar Zyklen. Beobachte mal das Zählregister. Das zählt nicht schön gleichmässig hoch. Und wenn da jetzt im Hintergrund ein Zählerüberlauf stattfindet dann wird der Compare Register update gemacht. > Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling > SOFORT!! upgedated. Ja. Ist bei mir auch so. Was sagt denn das Datenblatt dazu? Ich hab jetzt kein Datenblatt vom Mega48 da.
> Der Unterschied ist nur, dass > du bei einem Prescaler von 1 bei einem Druck auf F10 nicht einen > Taktzyklus ausführst sondern ein C Statement Das ist jetzt extrem schlecht ausgedrückt. Natürlich hängt ein F10 nicht davon ab welcher Prescaler eingestellt ist. Bei einem anderen Prescaler merkst du das nur nicht, weil der Timer nicht bei jedem Takt erhöht wird, sondern länger dazu braucht. Erst bei einem Prescaler von 1 merkt man dass da mehrere Takte für ein C-Statement draufgehen.
> Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling > SOFORT!! upgedated. >>Ja. Ist bei mir auch so. Was sagt denn das Datenblatt dazu? >>Ich hab jetzt kein Datenblatt vom Mega48 da. Also laut Datenblatt wird er genau gleich wie der timer0 upgedated. Müsste eigenlich ein BUG im AVR-Studio sein. schöne grüße
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.