Forum: Compiler & IDEs Komisches Verhalten meines Programms


von jaynis (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich steuere gerade eine Rundumleuchte per Mikrocontroller (Attiny2313) 
an. Je  nach dem ob Pin D2, Pin D3 oder Pin D4 auf LOW gesetzt ist, 
befindet sich die Leuchte in einem anderen Modus und erzeugt ein anderes 
Blink-Muster. Das funktioniert soweit auch ganz gut.

int main (void) {
  DDRB  = 0xFF;
  DDRD  = 0x00;
  PORTD = (1<<PD2) | (1<<PD3) | (1<<PD4);
  while(1) {
    if (!(PIND & (1<<PD2))) {
      blink();
    }
    if (!(PIND & (1<<PD3))) {
      rotate();
    }
    if (!(PIND & (1<<PD4))) {
      strobe();
    }
  }
  return 0;
}

Wenn ich nun aber 2 Pins gleichzeitig auf LOW setze, dann verhällt sich 
die Leuchte bzw. der Controller meines Erachtens ein wenig merkwürdig. 
Bei dem gleichzeitigen LOW setzen von bspw. Pin D2 und D3 müsste doch 
normalerweise erst blink() ausgeführt werden und danach dann rotate() 
und danach ginge es von vorn los. Aber in meinem Fall wird nur blink() 
aufgerufen und danach wieder blink() und wieder blink() usw. Wie als 
würde der Controller den Zustand von PD3 ignorieren bzw. nach dem 
aufrufen der ersten Funktion die Schleife neu beginnen. Bei anderen 
Kombinationen hat man übrigens das gleiche Problem. Es wird immer die 
Funktion aufgerufen, die im Quellcode als erstes genannt wird und danach 
geht es (in der Schleife) irgendwie wieder von vorne los.

Woran liegt das?

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht Layer-8-error?

Möglicherweise drückst du nicht lange genug....

Beispiel: Du drückst PD2 und PD3 für blink() und rotate().
Dann wird erst PD2 getestet und daraufhin blink() aufgerufen.
Erst nach blink() wird PD3 getestet, vielleicht hast du bis dahin schon 
losgelassen?

von Thomas E. (thomase)


Lesenswert?

Klaus Wachtler schrieb:
> Möglicherweise drückst du nicht lange genug....
Das wird es wohl sein.
Wenn du eine Taste drückst, muß das Programm das immer mitkriegen und 
sich das merken. Egal wann und wie lang das ist. Das tut es aber nicht, 
wenn es ewig in den Delays auf der Stelle trampelt.
Du bist jetzt an dem Punkt angekommen, wo du dich mit Timern und 
Interrupts befassen solltest.

mfg.

von Peter D. (peda)


Lesenswert?

Deine Routinen zerstören den Returnstack und damit fängst Du immmer von 
vorne an.


Peter

von Klaus W. (mfgkw)


Lesenswert?

> Deine Routinen zerstören den Returnstack

Wo denn?

von Peter D. (peda)


Lesenswert?

Klaus Wachtler schrieb:
> Wo denn?

War nur ne Vermutung.
Vielleicht falsches Target eingestellt und der Stack zeigt dadurch in 
den Wald.


Peter

von jaynis (Gast)


Lesenswert?

> Möglicherweise drückst du nicht lange genug....
Das kann es eigentlich nicht sein. Ich lege die besagten Pins per 
Schalter auf Masse. Das ich irgendeinen Druckknopf nicht lang genug 
drücke kann demnach eigentlich nicht sein. Die Pins sind nach dem 
Schalten fest und dauerhaft mit Masse verbunden. Dass es dort noch 
irgendwelche Wechselwirkungen durch Wackelkontakte o.ä. gibt sehe ich 
eigentlich als relativ unwahrscheinlich an.

> Deine Routinen zerstören den Returnstack und damit fängst Du immmer von
> vorne an.
Das klingt auf jeden Fall schon plausibler. Kannst du das weiter 
erläutern? Was bedeutet falsches Target und wo stellt man das ein?

von Karl H. (kbuchegg)


Lesenswert?

jaynis schrieb:

> Das klingt auf jeden Fall schon plausibler. Kannst du das weiter
> erläutern? Was bedeutet falsches Target und wo stellt man das ein?


Schau mal im AVR-Studio in den Projekt-Optionen nach, welcher 
Prozessor-Type eingestellt ist.

von jaynis (Gast)


Lesenswert?

Ich benutze kein AVR-Studio.

Ich mach alles "per Hand".

avr-gcc -std=c99 -Wall -Os -mmcu=attiny2313 -o main.elf  main.c
avr-objcopy -O ihex main.elf main.hex
avrdude -p t2313 -c usbasp -U flash:w:main.hex -B 10

:D


Das bietet natürlich einiges an Raum für Flüchtigkeitsfehler. Es kann 
natürlich durchaus angehen, dass ich hier aus Versehen mal nen anderen 
Prozessortyp gewählt habe, weil ich Zeitgleich mehrere Projekte mit 
unterschiedlichen AVRs am laufen habe. Ich werde das gleich/nachher mal 
checken.

von Oliver (Gast)


Lesenswert?

jaynis schrieb:
> Das bietet natürlich einiges an Raum für Flüchtigkeitsfehler.

Das bietet maximalen Raum für richtige Fehler.

Erzeuge dir doch mal ein makefile mit MFile, und nutze das.

Oliver

von Stefan E. (sternst)


Lesenswert?

jaynis schrieb:
> Ich mach alles "per Hand".

Und mit welchem avr-gcc auf welchem System?
Vielleicht unter Linux mit einem avr-gcc aus einem 
Distributions-Package?

von jaynis (Gast)


Lesenswert?

Oliver schrieb:
> Erzeuge dir doch mal ein makefile mit MFile, und nutze das.
Ja, ich wollte mir schon lange endlich mal ein Makefile gemacht haben, 
war bisher aber irgendwie zu faul dafür...

Stefan Ernst:
> Und mit welchem avr-gcc auf welchem System?
> Vielleicht unter Linux mit einem avr-gcc aus einem
> Distributions-Package?
Ja genau so. Ist das schlecht?


Jedenfalls habe ich die Einstellungen nun nochmal sorgfältig geprüft und 
den Controller nochmal geflashed. Nun funktioniert er auch so wie er 
soll. Ich war bei der Problemlösung irgendwie zu sehr auf meinen 
Quelltext fixiert und habe das ganze drumherum dabei vollkommen 
vernachlässigt.

Vielen Dank für eure Hilfen!

von Stefan E. (sternst)


Lesenswert?

jaynis schrieb:
> Stefan Ernst:
>> Und mit welchem avr-gcc auf welchem System?
>> Vielleicht unter Linux mit einem avr-gcc aus einem
>> Distributions-Package?
> Ja genau so. Ist das schlecht?

http://www.mikrocontroller.net/articles/AVR_und_Linux#Toolchain_beschaffen

von Karl H. (kbuchegg)


Lesenswert?

jaynis schrieb:
> Oliver schrieb:
>> Erzeuge dir doch mal ein makefile mit MFile, und nutze das.
> Ja, ich wollte mir schon lange endlich mal ein Makefile gemacht haben,
> war bisher aber irgendwie zu faul dafür...

Dann mach dir doch wenigstens ein Shell Skript, in das du die 3 Befehle 
hineinkopierst.
Ist dir das denn nicht zu blöd, die wieder und immer wieder einzutippen?

Makefile ist natürlich besser und im einfachsten Fall auch nicht 
aufwändiger als deine 3 Befehle.
So ein Makefile hat eine ganz einfache Syntax

Ziel : Quelle
<Tabulator> Kommando

Das 'Ziel' ist von der 'Quelle' abhängig und um das 'Ziel' zu erstellen, 
wird das 'Kommando' (oder die Kommandos) ausgeführt.
Fertig. Mehr ist das im einfachsten Fall nicht.

Dein Ziel ist das Hex-File. Um es zu kriegen, muss es ein elf File geben 
und es ist ein Kommando auszuführen (und das 2te Kommando nehmen wir 
auch gleich mit)
1
main.hex: main.elf
2
        avr-objcopy -O ihex main.elf main.hex
3
        avrdude -p t2313 -c usbasp -U flash:w:main.hex -B 10

Wo kommt das elf File her?
Das ensteht aus dem c-File.
Also 2. Regel
1
main.hex: main.elf
2
        avr-objcopy -O ihex main.elf main.hex
3
        avrdude -p t2313 -c usbasp -U flash:w:main.hex -B 10
4
5
min.elf: main.c
6
        avr-gcc -std=c99 -Wall -Os -mmcu=attiny2313 -o main.elf  main.c

und das wars auch schon für dein erstes Makefile. (Aufpassen: die Zeilen 
mit dem Kommando MÜSSEN mit einem Tabulator anfangen und nicht mit 
Leerzeichen). Im Grunde sind das also die Kommandos, die du sowieso 
schon eintippst und das ganze noch ergänzt um die Angabe der 
Abhängigkeiten. Bei 'Faulheit' geht es also nur darum, den Editor zu 
öffnen, die Kommandos einzutippen (was du sowieso in der Command Line 
schon tust), noch 2 Zeilen dazu und alles wieder abspeichern. Eine Sache 
auf 2 Minuten. Ich würde das daher eher umgekehrt sehen: Die Faulen 
machen sich ein Makefile. Die Hyperaktiven tippen jedesmal neu.

Das ganze nennst du 'makefile' und wenn du das Kommando 'make' gibts 
wird dein Projekt gebaut (und geflasht). Und du musst dir nie wieder 
Gedanken darüber machen, ob du für das jeweilige Projekt in der Command 
Line auch alle Compiler Optionen richtig eingestellt hast.


Und ja: Ich weiß. Generierte Makfiles sehen etwas anders aus. Das liegt 
aber daran, dass man da ins Makefile mehr Komfort eingebaut hat. Im 
einfachsten Fall tuts auch dieser 5 Zeiler.

von jaynis (Gast)


Lesenswert?

Danke für diese ausführliche Zusammenfassung, aber ich weis, was ein 
Makefile ist und auch wie dieses aufgebaut ist bzw. wie man eins baut 
;). In meinem Fall lag es schlicht und einfach an der puren Faulheit ;). 
Ich musste die Befehle nämlich nicht immer komplett neu eintippen, da 
sie in der Shell-History gespeichert waren und ich "nur" 3x mit der 
Pfeiltaste nach oben drücken musste um zum gewollten Befehl zu kommen 
(dies dann 3x für die 3 Befehle).
Ich hab mir immer gesagt, so lange ich nur an sonem Kleinkram rumfummel 
mach ich das mal eben so und wenn ich irgendwann mit einem größeren 
Projekt anfange baue ich mir ein richtiges Makefile. Und ehe man sich 
versieht wird der Kleinkram immer mehr zu was größerem ;).

von Karl H. (kbuchegg)


Lesenswert?

jaynis schrieb:

> Ich musste die Befehle nämlich nicht immer komplett neu eintippen, da
> sie in der Shell-History gespeichert waren und ich "nur" 3x mit der
> Pfeiltaste nach oben drücken musste um zum gewollten Befehl zu kommen
> (dies dann 3x für die 3 Befehle).

Das war mir schon klar.
Aber jede Entwicklungsmaschine wird auch mal abgeschaltet oder man 
unterbricht seine Arbeit. Oder lässt du deine Shells wochenlang 
durchlaufen, nur damit du die Command History nicht verlierst?

:-)

> Projekt anfange baue ich mir ein richtiges Makefile. Und ehe man sich
> versieht wird der Kleinkram immer mehr zu was größerem ;).

Ist immer so.

von Klaus W. (mfgkw)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Oder lässt du deine Shells wochenlang
> durchlaufen, nur damit du die Command History nicht verlierst?

Die History wird doch gespeichert, zumindest von meiner bash :-)

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Karl Heinz Buchegger schrieb:
>> Oder lässt du deine Shells wochenlang
>> durchlaufen, nur damit du die Command History nicht verlierst?
>
> Die History wird doch gespeichert, zumindest von meiner bash :-)

Oops. Sag schon nichts mehr.
Also "makfile ist böse, kaka, pfui. Nicht nutzen!"
:-)

von Peter D. (peda)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und ja: Ich weiß. Generierte Makfiles sehen etwas anders aus.

Oder das im Sample-Ordner des WINAVR, nur schlappe 617 Zeilen lang, 17kB 
groß.
Da wird natürlich jeder Einsteiger abgeschreckt und macht fürderhin 
einen großen Bogen ums Make.


Ich benutze eine Batch.
In jedem Projektordner eine eigene, da kann also nicht versehentlich das 
falsche Target compiliert werden.
Und am Schluß wird per STK500.EXE geflasht.
Ein Doppelklick auf die Batch und das neue Programm läuft.

Es kann allerdings passieren, wenn man mehrere Projekte gleichzeitig 
macht, daß man den Projektordner wechselt, aber vergißt, den ISP auf die 
andere Schaltung zu stecken. Die STK500.EXE prüft leider nicht das 
Target.


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.