Forum: Mikrocontroller und Digitale Elektronik ATMega32 INT0 Problem


von Andreas (Gast)


Lesenswert?

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
void sendUSART(char *);
12
void sendchar(unsigned char);
13
14
volatile uint16_t count=0;
15
16
17
ISR(INT0_vect)
18
{  
19
        count++;
20
  sendUSART("ISR\n");
21
    
22
}
23
24
void timer_start()
25
{
26
  TCCR0 |=(1<<CS02)| (1<<CS00);
27
}
28
29
void timer_stop()
30
{
31
  TCCR0 &= ~(1<<CS02)& ~(1<<CS00);
32
}
33
34
void init_USART(void)
35
{
36
  UCSRB |= (1<<TXEN);        
37
  UCSRC |= (1<<URSEL)|(3<<UCSZ0);  
38
  UBRRH = 0;            
39
  UBRRL = 103;            
40
}
41
42
43
44
void sendchar(unsigned char c)
45
{
46
  while(!(UCSRA & (1<<UDRE)));  
47
  UDR = c; 
48
}
49
50
51
52
void sendUSART(char *s) 
53
{
54
  while(*s)
55
  {
56
    sendchar(*s);
57
    s++;
58
  }
59
}
60
61
int main(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.

von Sascha W. (sascha-w)


Lesenswert?

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

von Jürgen S. (jurs)


Lesenswert?

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?

von Thomas E. (thomase)


Lesenswert?

Sascha Weber schrieb:
> Program
> für den richtigen Controller übersetzt?
Wenn es kein Hardwarefehler ist, bleibt da nicht mehr viel.

Jürgen S. schrieb:
> wenn ein "Interrupt-Overrun" ausgelöst wird
Autsch.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts

mfg.

von Jürgen S. (jurs)


Lesenswert?

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.

von bitte löschen (Gast)


Lesenswert?

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
1
MCUCR |= (1<<ISC01);
statt
1
MCUCR |= (1<<ISC00);
schreibst?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Georg G. (df2au)


Lesenswert?

Watchdog?

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.