Hallo,
ich experimentiere gerade mit den externen Interrupts des Mega32. Ich
habe daher ein Programm geschrieben, dass PC3 dauerhaft toggelt. PC3 ist
mit PD2 verbunden, sodass dauerhaft der externe INT0 ausgelöst wird.
Das Problem ist, dass jedesmal wenn der INT0 ausgelöst wird scheinbar
ein Reset ausgeführt wird.
Hier der Code, ich habe auch schon mehrere Varianten der ISR, bzw.
SIGNAL ausprobiert, jedoch ohne Erfolg.
1
#ifndef F_CPU
2
#define F_CPU 16000000UL
3
#endif
4
5
#include<avr/io.h>
6
#include<avr/interrupt.h>
7
8
#include<stdlib.h>
9
10
11
voidsendUSART(char*);
12
voidsendchar(unsignedchar);
13
14
volatileuint16_tcount=0;
15
16
17
ISR(INT0_vect)
18
{
19
count++;
20
sendUSART("ISR\n");
21
22
}
23
24
voidtimer_start()
25
{
26
TCCR0|=(1<<CS02)|(1<<CS00);
27
}
28
29
voidtimer_stop()
30
{
31
TCCR0&=~(1<<CS02)&~(1<<CS00);
32
}
33
34
voidinit_USART(void)
35
{
36
UCSRB|=(1<<TXEN);
37
UCSRC|=(1<<URSEL)|(3<<UCSZ0);
38
UBRRH=0;
39
UBRRL=103;
40
}
41
42
43
44
voidsendchar(unsignedcharc)
45
{
46
while(!(UCSRA&(1<<UDRE)));
47
UDR=c;
48
}
49
50
51
52
voidsendUSART(char*s)
53
{
54
while(*s)
55
{
56
sendchar(*s);
57
s++;
58
}
59
}
60
61
intmain(void)
62
{
63
64
PORTC|=(1<<PC3);
65
DDRC|=(1<<PC3);
66
67
DDRD&=~(1<<PD2);
68
PORTD|=(1<<PD2);
69
70
71
init_USART();
72
73
74
//Init extern INT0
75
MCUCR|=(1<<ISC00);
76
GICR|=(1<<INT0);
77
78
sendUSART("start\n");
79
80
sei();
81
82
83
while(1)
84
{
85
PORTC^=(1<<PC3);
86
}
87
}
Es wird immer wieder Start , ISR, Start, ISR,... ausgegeben.
Hallo,
also ich sehe erst mal nix was den Reset rechtfertigen würde. Program
für den richtigen Controller übersetzt?
Überleg mal:
wie schnell wird das togglen von PC3 erfolgen und wie lange wird die
UART-Ausgabe von "ISR\n" dauern?
Ist zwar in dem Fall hier egal, da das togglen während der UART-Ausgabe
wegen der ISR nicht weiterläuft.
Sascha
Andreas schrieb:> Das Problem ist, dass jedesmal wenn der INT0 ausgelöst wird scheinbar> ein Reset ausgeführt wird.
Vorbemerkung: Ich bin eher Anfänger als Profi bei der Programmierung von
Mikrocontrollern. Also sorry, wenn ich falsch liege.
Das Problem scheint für mich eher zu sein, dass der Controller-Reset
dann ausgelöst wird, wenn ein "Interrupt-Overrun" ausgelöst wird,
wodurch der Programmstack blitzschnell überläuft.
Leider überblicke ich Deinen cryptischen Code nicht so ganz, ich kenne
"nur" die Arduino-Plattform, wo fast alles in sprechende C-Routinen
gekapselt ist, aber ich meine zu erkennen, dass Du innerhalb der
Interrupt-Routine Text an die serielle Konsole ausgibst, korrekt?
Hast Du Dir schon mal ausgerechnet, wie lange die Textausgabe innerhalb
der ISR-Routine benötigt und wie schnell der nächste Interrupt ausgelöst
wird?
Darfst Du überhaupt "gefahrlos" die serielle Schnittstelle von einer
Interrupt-Routine aus ansprechen? Auf der Arduino-Plattform funktioniert
das zwar (entgegen der Beschreibung), wenn die Interrupts langsam genug
kommen, aber wenn die Textausgabe länger braucht als der nächste
Interrupt zum Feuern, dann knallt es blitzschnell. Ich glaube, die
Atmegas unter der Arduino-Plattform hängen dann in einer Dead-Lock
Dauerschleife fest statt ständig zu resetten.
Ich würde das mit der Textausgabe an die Schnittstelle innerhalb der
Interrupt-Routine mal ganz dringend weglassen.
Zähle stattdessen in der ISR nur den Counter hoch, nichts weiter! So
dass die ISR blitzschnell wieder beendet ist. Und gebe in der
Hauptschleife dann jeweils den Zählerstand aus! Als "volatile" hast Du
die Variable count ja bereits definiert, so dass Du diese sowohl in der
ISR hochzählen als auch in der Hauptschleife "sicher" ausgeben kannst.
Wahrscheinlich wirst Du dann merken, daß der Zählerstand häufiger per
ISR erhöht wird als er in der Hauptschleife ausgegeben wird, d.h. der
ausgegebene Zählerstand springt immer um mehrere Zahlenwerte nach oben.
Oder?
Thomas Eckmann schrieb:> Jürgen S. schrieb:>> wenn ein "Interrupt-Overrun" ausgelöst wird> Autsch.> http://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts
OK, ich hätte vielleicht besser "Interrupt-Blockade" schreiben sollen.
Mein Fehler.
Ein Interrupt mag zwar nicht den anderen direkt unterbrechen, aber wenn
die Interrupt-Behandlungsroutinen zu langsam abgearbeitet werden, dann
blockieren sich die Interrupts gegenseitig.
Dadurch werden am Ende nur noch die am höchsten priorisierten Interrupts
aufgerufen und ausgeführt, die niedrig priorisierten Interrupts kommen
gar nicht mehr zum Zuge. So kann das System nicht mehr funktionieren.
Für mich besteht das Problem einfach darin: Die Ausgabe der Zeichen an
die serielle Schnittstelle muß raus aus der Interrupt-Routine und rein
in die Hauptschleife verlegt werden.
Ist JTAGEN auch aus (unprogrammed)?
Im Handbuch steht auf Seite 60 zwar, dass ansonsten die Pins PC5:2 nicht
als normale I/Os benutzt werden können, aber nichts über die Folgen,
wenn man es dennoch versucht. Dass so etwas einen Reset auslöst, kann
ich erst mal nicht ausschließen.
Soweit ich das verstanden habe, ist PC3/TMS bei JTAGEN ein Eingang mit
aktiviertem Pullup, in Deinem Fall zusammengeschaltet mit einem anderen
Eingang mit aktiviertem Pullup, falls Du JTAG enabled hast. Das ergäbe
dauerhaft 1 und sollte eigentlich zu gar keinem Interrupt führen.
Insofern ist diese Fehlerursache unwahrscheinlich, da Bei Dir ja
Interrupts ausgeführt werden. Um das mal einzugrenzen: Was passiert,
wenn Du
Jürgen S. schrieb:> Ein Interrupt mag zwar nicht den anderen direkt unterbrechen, aber wenn> die Interrupt-Behandlungsroutinen zu langsam abgearbeitet werden, dann> blockieren sich die Interrupts gegenseitig.
Das mag bei anderen Prozessoren so sein, nicht jedoch beim Mega32. In
dieser AVR Familie ist dein Szenario, das du hier so sorgfältig
aufzubauen versuchst, erst mal nicht möglich.
> Für mich besteht das Problem einfach darin: Die Ausgabe der Zeichen an> die serielle Schnittstelle muß raus aus der Interrupt-Routine und rein> in die Hauptschleife verlegt werden.
Das sowieso.
Aber das ist erst mal kein Grund für einen Reset.
Nur mit dem Programm ist das beobachtete Verhalten nicht zu erklären.
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.