Forum: Compiler & IDEs Interrupt - falscher Rücksprung ?


von Niels Jacobsen (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit der Nutzung von Interrupts. Ich habe schon
länger daran rumprobiert und bin jetzt zur einfachsten Variante (siehe
unten) übergegangen. Das ganze soll eigentlich nur nach kurzer Zeit den
Ausgang von Aus auf An schalten.
Der Interrupt wird auch ausgelöst und der Ausgang kurzzeitig auf An
gesetzt - gleich danach wird das aber zurückgesetzt und der Ausgang
wieder Low gelegt.
Ich habe so die Vermutung, dass entweder nach dem Interrupt ein Reset
ausgeführt wird oder aber der Rücksprung aus dem Interrupt nicht klappt
- würde er vor die Funktion "einstellen" springen, würde der Ausgang
ja wieder low gelegt.

Ich wäre wirklich über jede Hilfe sehr dankbar.

Code:
#define _AVR_ATmega169_

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

void
einstellen (void)
{
  CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
  CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0); //Clock
geteilt durch 64

  DDRB = (1<<DDB6); //Pin7 an B auf Output
  PORTB = (0<<PB6); // und inaktiv

  TIMSK0 = (0<<OCIE0A)|(1<<TOIE0); //overflow enabled
  TCCR0A = (0<<WGM00)|(0<<WGM01)|(1<<CS02)|(0<<CS01)|(1<<CS00); //
prescaler 1024

  sei(); //globaler Interrupt an
}

SIGNAL (SIG_OVERFLOW0)
{
  PORTB = (1<<PB6);
}

int
main (void)
{
  einstellen ();
  for  (;;)
    ;
  return 0;
}

von Jörg Wunsch (Gast)


Lesenswert?

> #define __AVR_ATmega169__

Das darfst Du nicht tun, Macros, die mit einem Unterstrich beginnen,
sind reserviert.  Dieser Macro wird intern generiert in Abhängigkeit
von Deiner -mmcu Anweisung.  Vermutlich liegt genau hier auch der
Pfeffer im Hasen: Du wirst kein -mmcu haben, so daß der Compiler/
Linker Dir die Runtime für irgendwas (AT90S8515 oder was auch immer
der Default ist) zusammenbasteln, so daß weder Interruptvektortabelle
noch Stack-Initialisierung auch nur ansatzweise passen.

von Niels Jacobsen (Gast)


Lesenswert?

Hi,

danke für die Antwort - ich habe das jetzt rausgenommen und mit:

avr-gcc -mmcu=atmega169 test.c compiliert - danach dann noch das
HexFile erstellt:
avr-objcopy -j .text -O ihex a.out test.hex

Leider bleibt das Ergebnis das gleiche. Also wenn ich das auf den
Controller spiele, schaltet er den Ausgang kurz an und gleich wieder
aus.

Ist es möglich, dass er irgendwie falsch zurückspringt ?

von Jörg Wunsch (Gast)


Lesenswert?

Ich müßte im Datenblatt nachgucken, aber meiner Erinnerung nach kann
man bei ATmega169 den Watchdog per Fusebit einschalten.  Hast Du das
aus Versehen getan?

von Niels Jacobsen (Gast)


Lesenswert?

Hab mal im Datenblatt geschaut - es ist möglich per Fusebit den Watchdog
zu aktivieren aber dazu hätte ich das WDCE bit setzen müssen und
eigentlich habe ich damit gar nix gemacht.
Der Code der oben steht ist alles, was ich nutze... wird das in einer
der Includedateien vielleicht gemacht ?

von Jörg Wunsch (Gast)


Lesenswert?

Du wirfst hier ziemlich viel durcheinander.

Das Fusebit für den Watchdog heißt WDTON (in den high fuses) und hat
mit WDCE schlicht gar nichts zu tun.  Ob Du Deine Fusebits angefaßt
hast, hat nichts mit Deinem Code zu tun, sondern das tust Du vom
Programmiergerät aus.

Includedateien generieren durch bloßes Einfügen mit #include keinen
Code, können Dir also hier nichts geändert haben.

von Niels Jacobsen (Gast)


Lesenswert?

Guten Morgen,

hm das stimmt, dass mit WDTON und WDCE hab ich jetzt durcheinander
gebracht, weil ich noch geschaut habe, ob ich den Watchdog vielleicht
selbst eingeschaltet habe.
Mir ist noch ein anderes Phänomen eingefallen. Ich hatte auch mal
versucht die Interruptroutine länger zu machen - also einfach mit einer
Schleife, die nur immer wieder den Assemblerbefehl nop ausgeführt hat.
Trotzdem hat sich aber die Zeit, die der Port an war nicht verändert.

Ich schreibe den Code auf den AVR mit AVRProg - also aus dem AVR Studio
4 heraus. Bisher hatte ich aber nie ein Problem und es hat eigentlich
immer alles so funktioniert, wie ich das wollte - dieses Problem habe
ich erst, seitdem ich Interrupts nutzen will.
Übrigens: wenn ich die Zeitspanne nach der der Interrupt kommen soll,
ändere, verhält es sich alles genauso (was doch eigentlich heisst, dass
es nur schwerlich am Watchdog liegen kann, weil ich doch nicht
gleichzeitig diese Zeitspanne verändere - jedenfalls nicht bewusst :)
)

Danke nochmal für die Hilfe.

von Jörg Wunsch (Gast)


Lesenswert?

Vielleicht rufst Du ja testhalber einfach mal in der Hauptschleife
wdt_reset() auf?

von Niels Jacobsen (Gast)


Lesenswert?

Guten Morgen,

ich habe jetzt mal in der Hauptschleife wdt_reset() aufgerufen - da hat
sich nichts verändert. Dann habe ich noch versucht bei der
Initialisierung den WDT auszuschalten über:
  wdt_reset();

  WDTCR = (1<<WDTCE) | (1<<WDE);

  /* Turn off WDT */
  WDTCR = 0x00;

Geändert hat sich aber auch nichts - er schaltet den Pin immer kurz auf
high und dann gleich wieder low.

Hast du noch irgend'ne andere Idee ?

von Volkmar (Gast)


Lesenswert?

Hallo Niels,

Du schreibst:
| avr-gcc -mmcu=atmega169 test.c compiliert - danach dann noch das
| HexFile erstellt:
| avr-objcopy -j .text -O ihex a.out test.hex

Ich habe die Infos nicht hier, aber irgendwie vermisse ich den Linker.
Kann es sein, daß es daran liegt?

Volkmar

von Jörg Wunsch (Gast)


Lesenswert?

Nö, der Linker wird vom Compiler-Treiber (avr-gcc) aufgerufen, das ist
schon OK.

Ohne Debugger finde ich da jetzt auch kein Problem.

von Niels Jacobsen (Gast)


Lesenswert?

Hallo Volkmar,

also so wie es bisher gemacht habe, dachte ich, dass er es von selbst
link und ich habe immer eine datei a.out bekommen. Ich habe aber jetzt
nochmal folgendes gemacht:

avr-gcc -g -Os -mmcu=atmega169 -c test2.c
dann
avr-gcc -g -mmcu=atmega169 -o test2.out test2.o
und
avr-objcopy -j .text -O ihex test2.out test2.hex

Wie ich das sehe ist meine .out Datei in der anderen Methode kleiner
gewesen dafür aber der Hex File grösser. Trotz diesem Unterschied hat
sich aber daran, was der Controller macht, nichts geändert.

von Niels Jacobsen (Gast)


Lesenswert?

@Jörg

Was könnte ich denn da jetzt noch machen ?

von Matthias (Gast)


Lesenswert?

Hi

ich hab dein Programm mal mit dem AVRStudio simuliert. Da funktioniert
er.

Matthias

von Niels Jacobsen (Gast)


Lesenswert?

Hallo Mathias,

das habe ich auch gerade gemacht und es sieht wohl so aus, wie es soll
- aber was kann denn dann falsch sein ? So richtig ist mir die Sache
dann nicht klar.
Bei anderen Programmen hatte ich noch nie so ein Problem - nur seit ich
Interrupts nutzen will. Logisch ist das nicht, oder ?

von Jörg Wunsch (Gast)


Lesenswert?

Hmpf, was mir jetzt erst auffällt:

> TIMSK0 = (0<<OCIE0A)|(1<<TOIE0);

Du schaltest zwei Interrupts ein (output compare und overflow), aber
ich sehe nur einen Handler (overflow).  Damit schießt Dein output
compare ,,in die Luft'' und landet auf einem nichtzugewiesenen
Vektor.
Alle nichtzugewiesenen ISRs machen einen jmp 0.

von Niels Jacobsen (Gast)


Lesenswert?

Ich schreibe doch in das Output Compare eine 0 - also disable. Im
Datenblatt steht, dass es mit einer 1 eingeschaltet wird - also so wie
ich es gemacht habe, sollte eigentlich der Overflow an sein und der
Output Compare aus - oder nicht ?

Ich schreib mal schnell nen Handler dazu... ich hoffe, dass ist es :).

von Niels Jacobsen (Gast)


Lesenswert?

Hm,

also ich habe einmal den "OUTPUT_COMPARE0" Handler dazu gemacht, da
hat sich nichts geändert.
Dann habe ich noch den Aufruf
> TIMSK0 = (0<<OCIE0A)|(1<<TOIE0);
zu
TIMSK0 = (1<<TOIEO);
geändert... also fasse ich das Output Compare nicht an.

Leider bleibt alles das gleiche.

von Jörg Wunsch (Gast)


Lesenswert?

Ach was, ich hatte sowieso nur Deine etwas umständlich ausgedrückte
Null-Anweisung übersehen (0 << irgendwas).  Klar, daß das dann nichts
ändert.

Nö, ohne Debugger keine Idee mehr.  Leider ist der ATmega169 in meinem
STK502 (oder wie das Teil heißt) nicht mehr gewillt, mit mir zu reden,
so daß ich das auch nicht mal schnell mit einem JTAG-ICE durchspielen
kann.  (Ich muß mal gucken, ob ich den ATmega noch parallel
programmieren kann, seriell reagiert er weder im STK500 noch in einem
08/15 Parallelport-Dongle.)

von Niels Jacobsen (Gast)


Lesenswert?

Hallo (jetzt war die Seite aber lange down...),

ich wollte nur kurz sagen, dass ich es gefunden habe und einen Tipp
loswerden.
Nachdem Jörg das mit dem zusätzlichen InterruptHandler geschrieben hat,
dachte ich mir: egal, schreibste einfach für jeden Interrupt mal 'nen
Handler. Dann ging es und also habe ich nach und nach die Handler
wieder rausgenommen.
Zum Schluss hat sich rausgestellt, dass der PIN_CHANGE0 Interrupt
geworfen wurde... und natürlich nicht in meinem Code abgefangen.

Ich danke für jede Hilfe und vielleicht hilft meine Dummheit ja mal
einem anderen :)

Niels

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.