Hallo! Ich steh grad vor einem Rätsel! Einfache Aufhabe: Eine LED so ein paar mal blinken. Diese LED hängt an PIN PE0 #define ERROR_LED PE0 Dieser Port wird dann in der Main-Funktion als Ausgang definiert. DDRE = 0x1F; PORTE = 0xE0; (PORTS PE0 bis PE3 sind Ausgänge; PE5-PE7 sind Eingänge PE4 ungenutzt) Die LED ist High-aktiv. Momentan ist alles aus der Main-Funktion geflogen, was nichts mit dem Blinken zu tun hat. Führe ich diesen Befehl einzelnen aus: PORTE |= (1<<ERROR_LED); //High -> LED on Geht die LED an. Führe ich diesen Befehl einzelnen aus: PORTE &= ~(1<<ERROR_LED); //Low -> LED off Bleibt -oh Wunder- die LED aus. Kombiniere ich beide wie folgt: PORTE |= (1<<ERROR_LED); //High -> LED on PORTE &= ~(1<<ERROR_LED); //Low -> LED off Sieht man beim Reset für einen Bruchteil einer Sekunde die LED kurz aufleuchten. Auch korrekt. ABER! Sobald ich diese Kombinationen verwende bleibt die LED dauernd an: PORTE |= (1<<ERROR_LED); //High -> LED on _delay_ms(100); PORTE &= ~(1<<ERROR_LED); //Low -> LED off int i; for(i=0;i<3;i++) { PORTE |= (1<<ERROR_LED); //High -> LED on PORTE &= ~(1<<ERROR_LED); //Low -> LED off } Und jetzt das komplett Merkwürdige: int i; for(i=0;i<3;i++) { } PORTE |= (1<<ERROR_LED); //High -> LED on UND DIE LED GEHT NICHT AN!!!! Woran kann das liegen? Vielen Danl für Eure Hilfe! Gruß Jogi P.S.: Es geht um einen ATmega64 und AVR Studio 4.12 SP4 mit aktuellem WinAVR
*.lss!? Diesen Dateityp gibt es in meinem Projektverzeichnis nicht! Ist das nun ein gutes, oder schlechtes Zeichen? Gruß Jogi
Häng mal nen compilierbaren Code an, wo die LED nicht angeht, aber an sein sollte. Mit herausgerissenen Brocken kann keiner was anfangen. Peter
Achso! - Klar! Hier: //Processor frequency #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <stdint.h> #include <avr/interrupt.h> #include <util/delay.h> #include <inttypes.h> //definition data port #define ERROR_LED PE0 int main(void) { //Init ATMEL ATmega64 { DDRB = 0x00; //PortB -> input (Data from FTDI) PORTB = 0xFF; //activate PULL-Up for PORTB DDRC = 0xFF; //PORTC -> output (Control DAC) DDRD = 0xFF; //PORTD -> output (Data to DAC) DDRE = 0x1F; //PORTE -> input for RXF_FTDI (INT7=PE7), TXE_FTDI (INT6=PE6), Levelerror (INT5=PE5) // output for ERROR-LED (PE0), RD_FTDI (PE2), WR_FTDI (PE1) PORTE = 0xE0; //activate PULL-Up for INT7,INT6 and INT5 } //End Init ATMEL ATmega64 PORTE &= ~(1<<ERROR_LED); PORTE |= (1<<ERROR_LED); //flashing ERROR_LED 15x for ready int i; for(i=0;i<15;i++) { PORTE |= (1<<ERROR_LED); //High -> LED on PORTE &= ~(1<<ERROR_LED); //Low -> LED off } PORTE |= (1<<ERROR_LED); //High -> LED on //_delay_ms(100); //PORTE &= ~(1<<ERROR_LED); //Low -> LED off //PORTE |= (1<<ERROR_LED); //High -> LED on //PORTE &= ~(1<<ERROR_LED); //Low -> LED off while(1){ //Waiting for interrupts } //never goes here return 0; } Die anderen Funktionen habe ich rausgelöscht, da sie ja (noch) nicht aufgerufen werden und auskommentiert sind. Ich hoffe das Hilft!? Gruß Jogi
Achso, da ist noch ein kleiner Fehler dirn, der aber nichts an dem Fehler ändert: ... //flashing ERROR_LED 15x for ready int i; for(i=0;i<15;i++) { PORTE |= (1<<ERROR_LED); //High -> LED on //Später doll hier noch "_delay_ms(500);" stehen PORTE &= ~(1<<ERROR_LED); //Low -> LED off } //Hier habe ich Vergessen auszukommentieren //PORTE |= (1<<ERROR_LED); //High -> LED on //_delay_ms(100); ... Gruß Jogi
Zunächst einmal: Wenn ich Fehler suche, lasse ich mal alles weg, was nicht unbedingt nötig ist. Dein Beispiel-Code enthält noch viel unnötiges -- jedenfalls zu viel für mich. Was mir beim überfliegen auffällt: In der for-Schleife ist zwischen dem An- und Ausschalten kein Delay -- meine Augen können so schnell jedenfalls nicht gucken.
Ihr wolltet doch den Code. Der ausgeputzte Quellcode steht ja ganz oben und das war angeblich nicht ausrechend. Richtig, das Delay fehl in der for-Schleife. Momentan noch bewusst, was ich auch unten drunter geschrieben hab. Trotzdem müsste al Endeffekt die LED aus sein. Gebe ich nur die folgenden Codezielen ein: PORTE |= (1<<ERROR_LED); //High -> LED on _delay_ms(100); PORTE &= ~(1<<ERROR_LED); //Low -> LED off Bleibt die LED auch an. Und das dürfte sie auch nicht. Und in der _delay_ms()-Funktion ist auch ein for-Schleife enthalten. Deswegen meine Vermutung, dass es irgendwie mit der for-Schleife zusammenhängt. Nur warum!?
Ich habe mal Überflüssiges gelöscht, Pin E durch A ersetzt, weil bei mir gerade eine LED an A0 hängt. Ausserdem musste ich statt PA0 PINA0 schreiben , weiss gerade nicht warum. Bei mir läuft es: 0,3s an, 0,3s aus und dann blinken 15 mal. Du kannst wieder zurückersetzen A durch E, PINA0 durch PE0 oder PINE0 und probieren. #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <util/delay.h> #define ERROR_LED PINA0 int main(void) { DDRA = 0x1F; PORTA |= (1<<ERROR_LED); _delay_ms(100); _delay_ms(100); _delay_ms(100); PORTA &= ~(1<<ERROR_LED); _delay_ms(100); _delay_ms(100); _delay_ms(100); int i; for(i=0; i<15; i++) { PORTA |= (1<<ERROR_LED); _delay_ms(100); PORTA &= ~(1<<ERROR_LED); _delay_ms(100); } while(1); }
bedenke dass bei einigen boards der low-stand mit einer leuchtenden LED angezeigt wird. das nur für den fall, dass du ein board benutzt. das ist auch der fall wenn du deine LED lowaktiv betreibst. dein code sieht rein logisch und syntaktisch fehlerfrei aus (ich würde jedoch "#define ERROR_LED 0" machen). pumpkin
Du machst mir Angst! Es gibt da nämlich ein Problem: Das Board ist schon "zusammengenagelt". Sprich: Es ist alles fest auf einer Platine verlötet. Ich kann da leider nichts mehr an der Verdrahtung ändern! Gibt es vielleicht irgendwelche Einstellungen in der Software oder bei den Fuses, die man machen muss? Bei mir war alles neu - ATmega64 und Software- und ich habe nichts an den Grundeinstellungen geändert.
wenn es der grund ist dann ist es kein weltuntergang. gib mal schaltplan wenn du hast. pumpkin
und tu' dir selber einen gefallen: finger nicht an den fuses rum, die haben damit nichts zutun! das wollte ich nur noch gesagt haben. pumpkin
Ich hab jetzt den Code von Stefan Salewski einfach mal kopiert und PORTA zu E gemacht: #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <util/delay.h> #define ERROR_LED PINE0 int main(void) { DDRE = 0x1F; PORTE |= (1<<ERROR_LED); _delay_ms(100); _delay_ms(100); _delay_ms(100); PORTE &= ~(1<<ERROR_LED); _delay_ms(100); _delay_ms(100); _delay_ms(100); int i; for(i=0; i<15; i++) { PORTE |= (1<<ERROR_LED); _delay_ms(100); PORTE &= ~(1<<ERROR_LED); _delay_ms(100); } while(1); } Gleiches Spiel: Da blinkt nichts und die LED bleibt kontinuierlich an. :(
@pumpkin: Schaltplan? Port E0 geht zur LED über Widerstand auf Masse. - Nix besonderes. Oder interessiert dich was besonderes? Einfluss von anderen Eingängen?
>Ich hab jetzt den Code von Stefan Salewski einfach mal kopiert und PORTA >zu E gemacht:Gleiches Spiel: Da blinkt nichts und die LED bleibt >kontinuierlich an. Mögliche Ursachen wären: -- Port kaputt -- LED bekommt Dauerstrom (Kurzschluss) -- Compiler kaputt, generiert fehlerhaften Code -- Programmer kaputt Du hattest doch anfangs noch geschreiben, dass Du die LED dunkelschalten kannst? Geht das noch? Wenn ja mach mal ein Minimal-Programm, das die LED dunkel schaltet. Übrigens: Du weißt schon, das Ports oft mehrere Funktionen haben, also nicht nur als Ein- oder Ausgang dienen. Hast Du im Datenblatt nachgesehen, ob es da auf Deiner Platine mit anderen Dingen Konflikte geben könnte? Gruß Stefan Salewski
Also dunkel bleibt sie, wenn ich gar nichts mache, also den Port nicht ansteuer, oder wenn ich folgendes eingebe. PORTE &= ~(1<<ERROR_LED); //Low -> LED off Kombiniere ich An- und Ausschalten wie folgt: PORTE |= (1<<ERROR_LED); //High -> LED on PORTE &= ~(1<<ERROR_LED); //Low -> LED off sieht man beim Reset für einen Bruchteil einer Sekunde die LED kurz aufleuchten. - Aber danach ist und bleibt sie aus. Der Port PE0 hat noch folgende Funktion: RXD0/(PDI) Aber keine Ahnung, was ich damit anfangen soll!
>Der Port PE0 hat noch folgende Funktion: RXD0/(PDI) >Aber keine Ahnung, was ich damit anfangen soll! Du bist also einer dieser "Augen zu und durch" Typen? RX klingt nach Serieller Schnittstelle -- aber Du wirst ... Hast Du noch einen Port frei? Wenn ja, würde ich da irgendwie eine LED mit Vorwiderstand anklemmen und mein obiges Minimalprogramm für den Port anpassen und testen.
Ja, ist serielle Schnittstelle. Auszug aus dem Dtaenblatt: PDI/RXD0 – Port E, Bit 0 PDI, SPI Serial Programming Data input. During serial program downloading, this pin is used as data input line for the ATmega64. RXD0, USART0 Receive pin. Receive Data (Data Input pin for the USART0). When the USART0 Receiver is enabled this pin is configured as an input regardless of the value of DDRE0. When the USART0 forces this pin to be an input, a logical one in PORTE0 will turn on the internal pull-up. Such grad nach ne Option um die auszuschalten. Ein Port wäre noch frei. Aber ich hier grad kein Lötkolben zur Hand. Müsste ich dann morgen in der Schule machen.
Also ich ab jetzt das serielle Interface SPI über die Fuse deaktiviert. (Programmiere über JTAG) Aber das Problem bleibt weiterhin bestehen. ;(
Oder schmeiss #include <util/delay.h> und die delay() Funktion mal raus und ersetze sie durch eine primitive Leerschleife etwa int i; i=1; while (i++); Am besten Optimierung des Compilers abschalten, oder ein asm volatile ("nop"); in die Schleife, damit sie nicht wegoptimiert wird. Optimierung Abschalten ist eh mal zum Testen sinnvoll, wenn Problem auftreten. Und wenn das alles nicht hilft, muss man sich mal das Assembler-Listing ansehen. (Wie man das erzeugt steht im AVR-GCC Tutorial.)
Noch mal, um es zu verdeutlichen Steht in meinem Quellcode das drin: #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <util/delay.h> #define ERROR_LED PINE0 int main(void) { DDRE = 0x1F; PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); while(1); } Leuchtet die LED nach dem Reset kaum wahrnehmbar kurz auf und bleibt aus. Mache ich daraus: #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <util/delay.h> #define ERROR_LED PINE0 int main(void) { DDRE = 0x1F; PORTE |= (1<<ERROR_LED); asm volatile ("nop"); ... viele, viele "nops" asm volatile ("nop"); PORTE &= ~(1<<ERROR_LED); while(1); } Dann leuchtet die LED nach dem Reset kurz auf und bleibt dann aus. An und Ausschalten geht also!!! ABER: Steht im Quellcode das: #define F_CPU 1000000UL // 1 MHz #include <avr/io.h> #include <util/delay.h> #define ERROR_LED PINE0 int main(void) { DDRE = 0x1F; int i; for (i=0;i<15;i++){ PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); } while(1); } Bleibt die LED an, obwohl sie definitv aus sein müsste!!! Es liegt irgendwie an der for-Schleife!!!!
Naja, deine Darstellung des Problems ist ja immerhin schon deutlich prägnanter geworden -- so hat es sich für dich schonmal gelohnt. #include <util/delay.h> und #define F_CPU 1000000UL // 1 MHz ist nun aber überflüssig -- raus damit. Ich muss zugeben, dass ich etwas ratlos bin -- aber eben nur etwas. Das avr-gcc keine for-Schleife hinbekommt wäre schon seltsam. Wenn man allerdings unter Windows arbeitet ist alles möglich. Nach PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); ist die LED also aus -- wie es sein soll. Dann müsste sie nach int i; i=0; while(i<1) { PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); } auch aus sein. Und nach i=0; while(i<15) { PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); } auch usw. Nicht völlig auszuschließen wäre, dass der AVR mitten in der for-Schleife "abstürzt". Kannst Du nach der for-Schleife noch irgendwelchen Code ausführen. dessen Ergebnis man sehen bzw. überprüfen kann?
Zweimal nein. Also nach: int i; i=0; while(i<1) { PORTE |= (1<<ERROR_LED); PORTE &= ~(1<<ERROR_LED); } Bleibt die LED auch an. Und Befehle nach der for-Schleife werden nicht ausgeführt. (Hab einen anderen PIN einfach auf High setzen lassen, ohne for-Schleife gehts. Danach nicht.)
Hast Du mal das Hex-File simuliert ? Hast Du überhaupt ein Verify gemacht, daß das Programm im MC stimmt ? Peter
Du hast also ein kleines Testprogramm -- wenn Du den Code der for-Schleife auskommentierst wird der Code nach der for-Schleife ausgeführt. Wenn die for-Schleife durchlaufen wird, wird aber der Code nach ihr nicht ausgeführt. Dann sehe ich zwei Möglichkeiten: 1. Der Code der for-Schleife ist Fehlerhaft. Das ist unwahrscheinlich, aber nicht völlig auszuschliessen. Du müßtest den Assembler-Code ansehen bzw. posten -- und zwar ganz genau genommen müßtest Du den Code aus Deinen AVR auslesen. Könnte ja im Prinzip sein, dass der Fehler nicht von avr-gcc, sondern vom Programmer oder Flash des AVR resultiert. 2. Absturz des AVR in der Schleife -- vielleicht durch die Ströme beim Umschalten der LED. Sollte natürlich nicht passieren, habe ich auch nie erlebt. Mach mal irgendetwas anderes in der for-Schleife -- also keine großen Ströme schalten. Oder mach den Vorwiderstand der LED deutlich größer. Ja, kleine triviale Fehler können ganz schön Zeit kosten.
das layout wollte ich haben weil mich interessiert hat ob deine schaltung low- oder highaktiv ist. hat sich aber durch deine zusammenfassung aufgeklärt. ein tip von mir: check mal den brownout und watchdog. solche problemchen hatte ich mit den beiden auch schon. pumpkin
@Peter: Hast Du mal das Hex-File simuliert ? - Wie simuliert? Wie geht das? Hast Du überhaupt ein Verify gemacht, daß das Programm im MC stimmt ? - Ja. Standardmäßig eingestellt: Erase - Prgramm - Verify @Stefan: zu 1) Wenn du mir sagst, wo ich den Assembler-Code finde würde ich ihn gerne posten und mir selbst mal anschauen. In meinem Projektordner gibt es aber aus dem c-File, noch das Makefile, *.o, *.elf und *.o.d!?!? zu 2) Es handelt sich um eine Lowcurrent LED mit 7mA. Harmlos. Hab jetzt mal den Spieß umgedreht und folgenden Code probiert: PORTE &= ~(1<<ERROR_LED); int i; for(i=0;i<5;i++){ PORTE |= (1<<PE2); PORTE &= ~(1<<PE2); } PORTE |= (1<<ERROR_LED); Danach müsste ja am Ende die LED an und der Ausgang PE2 aus sein. Die LED bleibt aus. Auf dem Port PE2 "zabbelt" was rum. Da ich hier kein Oszi hab kann ich nicht genau bestimmen was. Messbar ist eine DC-Spannung von 1,2V, was auf eine PWM hindeutet (0V/5V). Somit erweckt es den eindruck, dass er nicht aus der for-Schleife rauskommt. (PE2 ist ein Eingang zu einem anderen Baustein) @pumpkin: LED ist defintiv High-aktiv. Die Einzel-Befehle funktionieren auch. Was meinst du mit brownout und watchdog? Nach den Fuses ist "Watchdog timer always on" deaktiviert; Brown-out detection level at VCC=2,7V (BODLEVEL=1) aktiviert und Brown-out detection enabled (BODEN=0) deaktiviert.
ok. hast du den "ATmega103 compatibility mode" per fuse ausgeschaltet? interessant auch: "When the USART0 Receiver is enabled this pin is configured as an input regardless of the value of DDRE0.". pumpkin
Der "ATmega103 compatibility mode" ist noch aktiviert! Was bewirkt der? "When the USART0 Receiver is enabled this pin is configured as an input regardless of the value of DDRE0.": Ja wenn er denn definiert ist. Aber ddann würde das ein und ausschalten "so" nicht gehen (von der for-Schleife mal abgesehen) und das hätte ja dann auch nichts mit dem Port PE2 zu tun.
AAAAAAAAAAAAAAAAAARRRRGGGGGG!!! Ich bekomm die Krise!!!! SIE BLINKT!!!! Hab jetzt den "ATmega103 compatibility mode" deaktiviert! Was bedeutet dieses Sch*teil?? Vielen Dank an alle, die mir geholfen haben! Besonders pumpkin!!!!
>@Stefan: >zu 1) Wenn du mir sagst, wo ich den Assembler-Code finde würde ich ihn >gerne posten und mir selbst mal anschauen Ich erzeuge unter Linux das Assembler-Listing mit avr-objdump, beschrieben etwa auf http://www.roboternetz.de/wissen/index.php/Hallo_Welt_f%C3%BCr_AVR_%28LED_blinken%29 Wie das unter Windows geht sollte dir besser ein anderer erklären. Simulieren: Mit AVR-Studio kann man doch Programme Schritt für Schritt am Bildschirm durchlaufen lassen. Watchdog: Macht nach einer bestimmten Zeit einen Reset, wenn er nicht rechtzeitig zurückgesetzt wird. Ist aber vorgabemäßig deaktiviert. Brownout: Reset wenn die Spannung einen bestimmten Wert unterschreitet. Das nur als Stichworte. >interessant auch: "When the USART0 Receiver is enabled this pin is >configured as an input regardless of the value of DDRE0.". Ich hatte ja geschrieben, dass man Konflikte mit anderen Funktionen beachten muss. Aber deshalb sollte er sich ja nicht in der for-Schleife festfressen?
was der macht steht im manual. Seite 80, "Alternate Functions of Port E". nix zu danken. pumpkin
Jogi wrote: > Hab jetzt den "ATmega103 compatibility mode" deaktiviert! > > Was bedeutet dieses Sch*teil?? Daß sobald ein Call erfolgt, das Programm in den Wald geht, da der M103 weniger SRAM hatte. Der SP wird auf einen Bereich gesetzt, der beim Mega103 ungültig war. Wenn Du Mega128 gesagt hättest, hätte ich das auch vermutet. Aber daß der Mega64 diese Fuse auch hat, wußte ich bisher noch nicht. 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.