Hallo Leute! Ich hab hier ein kleines, einfaches Programm. Allerdings wird der Code unlogisch und FALSCH auf meinem AVR ausgeführt! Die Sitution ist folgende: am Port C hängt eine LED. Der folgende Code schaltet diese ein, und dann nach 2 Sekunden aus. So: //-------------- INCLUDES ------------------------------------------------ #include <avr/io.h> // Input/output an den Pins #include <avr/interrupt.h> // Interrupts //-------------- DEFINES ------------------------------------------------ #define FRAMES_PER_MS 11 //-------------- GLOBALS ------------------------------------------------ unsigned int msCounter = 0; // MilliSekunden Zähler //-------------- PROTOTYPES ------------------------------------------------ void ledAus( void ); int main(void) { // Timer initialisieren TCCR0 |= (1<<CS00)|(1<<CS02); DDRC = 0xff; // C als Ausgang PORTC = 255; // C anschalten // MainLoop while(1) { // Timer und MS aktualisieren if( TCNT0 > FRAMES_PER_MS ) // Eine Millisekunde ist vergangen { TCNT0 -= FRAMES_PER_MS; msCounter++; if( msCounter > 2000 ) // Alle 2 Sekunden... { msCounter -= 2000; ledAus(); //PORTC = 0; // -HIER OBACHT WICHTIG!!! }//end if }//end if }//end while }//end main void ledAus( void ) { PORTC = 0; }//end doSingleBeep Es sollte sofort klar sein, was dieser Code tut ;-) Jetzt aber zum Problem: Eigentlich sollte es ja keinen Unterschied machen, ob die Zeile mit "PORTC = 0; // -HIER OBACHT WICHTIG!!!" drin ist oder nicht. Der Port wird ja so oder so auf 0 gesetzt.... Aber halt! Das wird er eben nicht!!! Wenn ich die Zeile nämlich rauskommentiere, bleibt die LED leuchtend. Nur mit dieser Zeile geht sie aus. Was soll das? Kann es sein, dass die Funktion "ledAus" garnicht ausgeführt wird??? Ist mein C-Verständnis falsch, oder was könnte hier das Problem sein? Danke für eure Hilfe!!!
Hi Peter! Ich hab mal danach Gegoogelt, bin aber nicht wirklich schlau draus geworden... Was ist so ein Fuse eigentlich, und viel Wichtiger: kann ich diesen bösen M103 irgendwo an/aus schalten?
Zunaechst mal sollten wir etwas abklaeren: Arbeitest Du mit einem Mega128? Nur bei diesem Prozessor gibt es diese Fuse und koennte das von dir beobachtete Verhalten erklaeren.
Nein, tu ich nicht. Ich habe einen 90815 dingsbums ;-) Aber wenn es daran nicht liegt, was soll es dann sein? Der Code ist doch Wasserdicht!!! creeep
"Ich habe einen 90815 dingsbums" Wenn Du jetzt noch die richtige und vollständige Bezeichnung angibst und das bereits am Anfang getan hättest, hätten wir uns ne Menge Rumraterei gespart. Peter
>Aber wenn es daran nicht liegt, was soll es dann sein? Der Code ist >doch Wasserdicht!!! Eben nicht! > if( TCNT0 > FRAMES_PER_MS ) // Eine Millisekunde ist vergangen Hier ist TCNT0=FRAMES_PER_MS +1 > { > TCNT0 -= FRAMES_PER_MS; // 1 bleibt übrig TCNT0 erhöht sein Inhalt bei jedem Durchlaf (1,2,3...) und am ende ist Bendigung if(TCNT0 > FRAMES_PER_MS) immer erfült bis zum Überlauf. TCNT0 =0; // Sollte richtig sein >if( msCounter > 2000 ) // Alle 2 Sekunden... > { > msCounter -= 2000;//??? msCouter=0; // oder noch besser: if( msCounter >= 2000 ) { msCouter=0; Branko
Das Timing ist ja garnicht so wichtig. Das funktioniert sogar! Das Problem ist ja ein anderes - nämlich dass mit der rauskommentierten Zeile... (im andren Fall geht die LED genau nach 2 Sek. aus!)
Wenn ein Bug im AVR-GCC vermutet wird, dann braucht man zur Kontrolle mindestens die Versionsnummer des GCC. Damit kann man in der Buglist http://rtems.org/phpwiki/index.php/GCCAVRBugs nachsehen. Nicht schlecht wären z.B. Angaben zu eventuell verwendeten Optimierungseinstellungen und ggf. auch noch die produzierte Assemblerdatei (*.s).
Ich habe (GCC 3.4.4, -Os) das Ganze im VMLAB simuliert, und nachdem der Counter die 2000 erreicht hat, schaltet die LED korrekt um (bei mir ist sie dann ein, da in VMLAB die LEDs gegen Vcc geklemmt werden). Sie schaltet natürlich nie wieder zurück, weil du diese Funktionalität nicht implementiert hast. Wäre auch schön, wenn du statt magischer Konstanten lieber die CPU-Frequenz mit hingeschrieben hättest und dann den Wert 11 für die Millisekunde daraus abgeleitet (per Formel). Compiler können selbst rechnen, man muss also nicht unbedingt alles mit dem Taschenrechner vorher ausrechnen.
"Wäre auch schön, wenn du statt magischer Konstanten lieber die CPU-Frequenz mit hingeschrieben hättest und dann den Wert 11 für die Millisekunde daraus abgeleitet (per Formel)" Darum gehts es ja auch garnicht ;-) Man könnte das mit dem Timing glaubich vollkommen ignorieren. Es ist ja nur so, dass die LED irgendwann ausgehen soll. Egal ob jetzt genau 2 Sekunden oder nicht. "Angaben zu eventuell verwendeten Optimierungseinstellungen und ggf. auch noch die produzierte Assemblerdatei (*.s)." Oha, da hab ich gar keine Ahnung (habe nichts bestimmtes eingestellt...)
Stell doch einfach mal den wirklichen Quelltext, einmal den funktionierenden und einmal den nicht funktionierenden als Anhang rein. Oftmals sind Leute nicht dazu fähig, d.h. sie stellen etwas völlig anderes rein, als das, was sie ausprobiert haben. Und dann sucht man sich natürlich dumm und dämlich. Probier auch mal aus, ob es einen Unterschied macht, ob das main() oder ledAus() die letzte Funktion ist. Mit ledAus() als letzte Funktion klappt nämlich das Einfügen des Quelltextes ins Listing nicht mehr, d.h. das Listing ist schwerer zu lesen. Peter
OK, ich habe den Code jetzt so umgestrickt, dass er nur noch halb so lang ist, und ohne Timer auskommt. Aber immernoch macht das Ding totalen Quatsch! Für alle, die's nicht runterladen wollen: Code 1 (LED leuchtet nicht!!!): //-------------- INCLUDES ------------------------------------------------ #include <avr/io.h> // Input/output an den Pins #include <avr/interrupt.h> // Interrupts void ledAus( void ) { }//end ledAus int main(void) { DDRC = 0xff; // C als Ausgang PORTC = 255; // C anschalten while(1) {;} }//end main Code 2 (LED leuchtet!!!): //-------------- INCLUDES ------------------------------------------------ #include <avr/io.h> // Input/output an den Pins #include <avr/interrupt.h> // Interrupts //void ledAus( void ) //{ //}//end ledAus int main(void) { DDRC = 0xff; // C als Ausgang PORTC = 255; // C anschalten while(1) {;} }//end main Wie ihr seht ist nur die eine Funktion herauskommentiert, DIE ABER DOCH GAR KEINE AUSWIRKUNGEN AUF DAS PROGRAMM HABEN DÜRFTE!!!! Oder sehe ich da was falsch??? Danke für eure Hilfe! :-)
Programm ist korrekt, Ergebnis ist korrekt. Bei mir jedenfalls. Daher wird's nötig, dass du deutlich mehr als bisher rausrückst - Compiler/Winavr-Version, in welcher Umgebung du das baust, evtl. das Makefile oder APS-File, oder was auch immer du verwendest, Info über den kompletten Weg mit dem du vom C-File zum Controller kommst. Denn mit der von dir bisher gelieferten Info ist das schlichtweg nicht reproduzierbar und auch nicht zu erraten.
Der M103-Fehler ist im Prinzip der, daß man für ein falsches Target kompiliert. Kann also auch mit dem AT90S8515 passieren, wenn Du den nicht als Target gesetzt hast. Peter
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.