Forum: Compiler & IDEs Probleme mit for-Schleifen


von Jogi (Gast)


Lesenswert?

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

von Ulrich (Gast)


Lesenswert?

kannste mal das *.lss file oder so mal reinkopieren?

von Jogi (Gast)


Lesenswert?

*.lss!?

Diesen Dateityp gibt es in meinem Projektverzeichnis nicht!

Ist das nun ein gutes, oder schlechtes Zeichen?

Gruß
Jogi

von Peter D. (peda)


Lesenswert?

Häng mal nen compilierbaren Code an, wo die LED nicht angeht, aber an 
sein sollte.

Mit herausgerissenen Brocken kann keiner was anfangen.


Peter

von Jogi (Gast)


Lesenswert?

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

von Jogi (Gast)


Lesenswert?

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

von Stefan Salewski (Gast)


Lesenswert?

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.

von Jogi (Gast)


Lesenswert?

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!?

von Stefan Salewski (Gast)


Lesenswert?

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);

}

von pumpkin (Gast)


Lesenswert?

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

von Jogi (Gast)


Lesenswert?

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.

von pumpkin (Gast)


Lesenswert?

wenn es der grund ist dann ist es kein weltuntergang. gib mal schaltplan 
wenn du hast.

pumpkin

von pumpkin (Gast)


Lesenswert?

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

von Jogi (Gast)


Lesenswert?

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. 
:(

von Jogi (Gast)


Lesenswert?

@pumpkin: Schaltplan?
Port E0 geht zur LED über Widerstand auf Masse. - Nix besonderes.

Oder interessiert dich was besonderes?
Einfluss von anderen Eingängen?

von Stefan Salewski (Gast)


Lesenswert?

>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

von Jogi (Gast)


Lesenswert?

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!

von Stefan Salewski (Gast)


Lesenswert?

>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.

von Jogi (Gast)


Lesenswert?

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.

von Jogi (Gast)


Lesenswert?

Also ich ab jetzt das serielle Interface SPI über die Fuse deaktiviert.
(Programmiere über JTAG)
Aber das Problem bleibt weiterhin bestehen. ;(

von Stefan Salewski (Gast)


Lesenswert?

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.)

von Jogi (Gast)


Lesenswert?

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!!!!

von Stefan Salewski (Gast)


Lesenswert?

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?

von Jogi (Gast)


Lesenswert?

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.)

von Peter D. (peda)


Lesenswert?

Hast Du mal das Hex-File simuliert ?

Hast Du überhaupt ein Verify gemacht, daß das Programm im MC stimmt ?


Peter

von Stefan Salewski (Gast)


Lesenswert?

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.

von pumpkin (Gast)


Lesenswert?

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

von Jogi (Gast)


Lesenswert?

@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.

von pumpkin (Gast)


Lesenswert?

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

von Jogi (Gast)


Lesenswert?

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.

von Jogi (Gast)


Lesenswert?

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!!!!

von Stefan Salewski (Gast)


Lesenswert?

>@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?

von pumpkin (Gast)


Lesenswert?

was der macht steht im manual. Seite 80, "Alternate Functions of Port 
E".

nix zu danken.

pumpkin

von Peter D. (peda)


Lesenswert?

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
Noch kein Account? Hier anmelden.