Hallo,
vielleicht kann jemand mal einen kurzen, aber fachmännischen Blick auf
den unten stehenden Code werfen, den ich bewusst extem einfach gehalten
habe. Und trotzdem funktioniert es nicht nach meinen Vorstellungen. In
"main()" wird eigentlich nur der externe Interrupt INT0 initialisiert
und dann gewartet. Der Sprung in die Routine klappt auch, allerdings
lande ich beim Rücksprung wieder bei "int i=0" in "main()".
Eigentlich müsse ich aber doch immer in der Endlosschleife "while
(1)" landen. Das Ganze läuft auf dem ICCAVR von Imagecraft.
Weiß jemand, warum dem nicht so ist?
vielen Dank
Jürgen
________________________________________________
#include <iom8535v.h>
#pragma interrupt_handler INT0_handler: INT0
void INT0_handler (void);
void init (void);
void main (void)
{
int i=0;
MCUCR = 0x03;
SREG |= 0x80;
GICR = 0x40;
while (1);
}
void INT0_handler(void)
{
i++;
}
ich kann zwar kein c, aber in den anderen Sprachen (asm und Bascom)
brauchen die interruptroutinen einen expliziten reti.
Könnte vielleicht eine Lösungsidee sein??
grüsse leo9
Hallo,
@Tux: Auch eine globale Variable löst das Problem nicht
@Matthias: Hardwaremäßig habe ich es ehrlich gesagt noch nicht
ausporbiert. Es handelt sich um einen Atmega8535.
Hi,
hast Du schonmal ins listing des Compilers geschaut? Da erkennt man oft
mehr. Vielleicht muss man die Interrupt-Routine anders deklarieren. Ich
denke allerdings auch, dass i global sein muss.
Viele Grüße,
Ralf
muss ja global sein, sonst hätte der Compiler das ja nicht übersetzt,
was soll er denn mmit i++ machen, wenn er i nicht kennt?
Was mich wundert: wieso steht da zweimal: "void INT0_handler(void)",
müsste doch auch einen Compilierungsfehler erzeugen?
Hallo,
"void INT0_handler(void)" kommt zweimal vor, da es sich beim ersten
mal um die Deklaration, beim zweiten mal um die Definition handelt. Ich
hoffe ich bring nicht alles durcheinander :) Jedenfalls denke ich, das
hat seine Richtigkeit. Es wird ja alles fehlerfrei compiliert und ich
kann ja bis auf den Rücksprung aus der Routine alles einwandfrei
simulieren.
Jürgen
Ich kenne den ICCAVR nicht.
Aber mach doch testweise einfach mal das int i = 0; in der main weg.
Ich vermute mal, daß dir der Debugger dieses i anzeigt. Das ist aber
nur lokal in main. Bei dem anderen muß es sich um eine andere Variable
handeln. Wo die allerdings deklariert wird weiss ich nicht.
Variable i ist in main deklariert, weshalb es in der Interrupt-Funktion
gar nicht sichtbar ist. Eigentlich haette der Compiler hier ein Error
ausgeben muessen.
Wenn Du i ausserhalb von main deklarierst, sollte es klappen.
MfG
Hallo Juergen,
ich kenne mich zwar nicht mit dem ICCAVR aus, aber beim avrgcc werden
Konstrukte wie while (1) z.T. wegoptimiert, wenn man die Optimierung
nicht explizit ausschaltet.
Ich verwende im Hauptprogramm meistens solche Schleifen
for(;;){
tastenabfrage();
warten(x);
}
Hoffe, dir weitergeholfen zu haben.
MfG
Marcel
Hallo MooseC,
bei mir stehen folgende Interrupt_Vektoren in der include-Datei
"iom8535v.h":
__________________________________________________
/* General Interrupts */
#define GIFR (*(volatile unsigned char *)0x5A)
#define INTF1 7
#define INTF0 6
#define INTF2 5
#define GIMSK (*(volatile unsigned char *)0x5B)
#define GICR (*(volatile unsigned char *)0x5B)
#define INT1 7
#define INT0 6
#define INT2 5
#define IVSEL 1
#define IVCE 0
____________________________________________________
Ich verstehe nicht, woher du da iv_INT0 nimmst.
Aber wie ich sehe liegt das Problem wohl eher beim Simulieren mit
AVR-Studio. Selbst bei unten stehendem "Progrämmchen" stimmt der
gelbe Pfeil mit den Tatsachen überhaupt nicht überein.
#include <iom8535v.h>
___________________________
void main ()
{
MCUCR = 0x03;
SREG |= 0x80;
GICR = 0x40;
while (1);
}
____________________________
Wenn ich mir das Ganze aber in der "Disassembler"-Ansicht ansehe,
dann sehe ich, dass das Programm richtig abläuft, während sich der
gelbe Pfeil in der Normalansicht ausserhalb des Codes befindet.
Naja, da kann ich wohl nicht viel machen. Vielleicht mal sehen, ob es
bei Atmel irgendwelche Updates vor das Studio gibt.
Jürgen
Hallo Jürgen,
du kannst in einer Interrupt-Routine nur auf globale Variablen
zugreifen und diese müssen dann auf jeden Fall als "volatile"
deklariert sein. Damit wird angegeben, dass die Variable auch außerhalb
des normalen Programmablaufs geändert werden kann (-> in einer
Interrupt-Routine).
volatile int i;
Gruß,
Olaf
Hallo Olaf,
mir gehts nicht so sehr um den Zugriff auf Variablen. Das Beispiel habe
ich rein zufällig so gewählt. Von mir aus macht die Routine auch
nichts. Das komische ist halt der Rücksprung, da der nicht richtig
erfolgt.
Tja, so wurde aus meinem kleinen C-Problem doch ein großes :)
Jürgen
... ein wirkliches Problem gibt es hier anscheinend gar nicht. Wenn man
"Schrott" (Entschuldigung für diesen Ausdruck) programmiert, dann
darf man sich auch nicht über das Verhalten des Debuggers wundern
(unabhängig davon, ob und warum und wie der Code übersetzt wurde). Du
schraubst ja auch nicht einfach ein viereckiges Rad an dein Auto und
wunderst dich danach über die komischen Fahreigenschaften, gell?
Vielleicht verhält der Debugger sich so wie du es erwartest, wenn du es
mit einem vernünftigen Programm probierst ;o)
Gruß,
Olaf
Hallo Jürgen,
>>bei mir stehen folgende Interrupt_Vektoren in der include-Datei
"iom8535v.h":
>>____________________________________________________
/* General Interrupts */
#define GIFR (*(volatile unsigned char *)0x5A)
#define INTF1 7
#define INTF0 6
#define INTF2 5
#define GIMSK (*(volatile unsigned char *)0x5B)
#define GICR (*(volatile unsigned char *)0x5B)
#define INT1 7
#define INT0 6
#define INT2 5
#define IVSEL 1
#define IVCE 0
____________________________________________________>>Ich verstehe nicht, woher du da iv_INT0 nimmst.
Hmm, das sind nicht die Interruptvektoren, sondern Bitdeklarationen
einiger im Mega8535 vorhandenen Interruptbits für Flags und Enable.
Die Interruptvektoren heißen in der iom8535v.h vom ICCAVR auch so -
siehe Anhang ganz unten.
Dein Vektor ist auf jeden Fall mit INT0 verkehrt, da es mit 6 nicht den
Vektor beschreibt, sondern das Enblebit im GICR.
MooseC
Hallo MooseC,
wenn ich heute heimkomme, schau ich mir das nochmal genauer an.
Vorerst einmal vielen Dank für deine Hilfe. Irgendwie wirds dann schon
noch klappen.
Jürgen
Ich kenn mich mit uController nicht gut aus.
Aber sollte nicht in der interrupt routine am ende ein "return "
stehen?
Ich vermute mal, da du die interupt routine vor main inizierst, dass
der Code im speicher des controllers vor der main steht und du dann
logischerweise immer am anfang der main landest nachdem der interrupt
ausgefürt wurde.
Hallo,
an alle vielen Dank für die Unterstützung. Hat mir geholfen, Neues zu
lernen und mein Problem zu lösen.
@MooseC: Natürlich hast du recht, die Sache mit den Interruptvektoren
habe ich total verpeilt :)
Die Simulation mit AVR Studio hat nur nicht geklappt, weil man die
Datei \icc\libsrc.avr\iostudio.s aus dem icc-Ordner in den den
aktuellen Projektordner kopieren muss. Diese Information habe ich erst
heute in der Hilfe gefunden.
Trotzdem noch mal vielen Dank an alle.
Jürgen