Forum: Compiler & IDEs Interruptproblem Atmega32


von Christian (Gast)


Lesenswert?

Hallo Forum

Möchte mit einem Taster einen Interrupt auslösen (INT0).
Wenn ich den internen PullUp aktiviere und den Taster aug GND hänge 
funktioniert alles wunderbar. Einziges Problem ist, dass ich den Taster 
drücke und erst beim auslassen der Interrupt auslöst. Ist auch klar, da 
ich auf steigende Flanke programmiert habe.

Wenn ich allerdings beim Drücken des Tasters den Interrupt auslösen 
möchte und den Taster auf +5V hänge, wird bereits bei der 
Programmübertragung der Interrupt aktiviert (LEDs der Interruptroutine 
leuchten auf).
Da der Eingangspin von INT0 immer einen definierten Wert braucht habe 
ich einen externen PullDown dazwischengeschaltet. Somit liegt permanent 
GND am Eingangspin, nur beim drücken des Tasters kurzfristig +5V.

Meine Frage:
Warum funktioniert alles wenn ich den internen PullUp verwende und GND 
taste, aber bei einem externen (PullDown) und +5V nicht?
1
#include <avr/io.h>
2
#define F_CPU 8000000UL
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6
7
volatile unsigned char x = 1;     // volatile immer für Variablen, die im  
8
volatile unsigned char NeueZahl = 0;  // Hauptprogramm und in der
9
                                      //Interruptroutine verwendet werden
10
11
ISR(INT0_vect){
12
13
  unsigned char g = 224;  // PORTC erkennt nur Zahlen kleiner als 128,
14
  PORTC = ~g;             // deshalb Variable eingeführt
15
  _delay_ms(1000);
16
17
  x++;
18
  NeueZahl = 1;  // True der If-Bedingung
19
}
20
21
22
23
int main(void){
24
 
25
   DDRC = 0xFF;
26
   PORTC = ~0x60;
27
   _delay_ms(1000);
28
 
29
   //PORTD = 0xFF;  // PullUp aktivieren!!  oder externen PullUp aktivieren
30
31
   // Interrupts aktivieren
32
   SREG |= (1<<7);    // Global Interrupt Enable     sei(); als Alternative
33
   GICR |= (1<<INT0);   // External Interrupt 0 Enable
34
   MCUCR |= (1<<ISC01)|(1<<ISC00);   // Int0 auf steigende Flanke
35
 
36
 
37
   while(1){
38
 
39
      PORTC = ~7;
40
      _delay_ms(500);
41
42
      if(NeueZahl){
43
   
44
         PORTC = ~x;
45
         _delay_ms(1000);
46
         NeueZahl = 0; // If-Bedingung wieder auf 0 setzten,
47
                       // damit nächster Interrupt diese wieder 
48
                       // aufrufen kann
49
      }
50
   }
51
}

von Karl H. (kbuchegg)


Lesenswert?

Ich denke die Frage sollte eher lauten:
Wie wirkt sich eigentlich ein bestimmter Pegel an diesem Pin aus, 
solange der externe Interrupt nicht konfiguriert ist?

In deinem internen Pullup Szenario, aktivierst du den Pullup bevor du 
den Interrupt freischaltest und konfigurierst (da solltest du übrigens 
noch einmal über die Reihenfolge nachdenken: normal ist wohl, dass 
zuerst eine Einheit konfiguriert ehe man sie dann zur Arbeit 
freischaltet und nicht umgekehrt). Wird der Interrupt freigegeben, dann 
hat er noch die Default-Einstellung von: Interrupt an aktive Low. Das 
hast du aber durch den Pullup nicht mehr am Pin. Dort ist schon high. 
Und erst dann schaltest du auf Edge Detection um.

In deinem Szenario mit externem Widerstand ist aber der Ablauf der 
Ereignisse so:
der Widerstand zieht den Pin auf Low.
Du aktivierst die Interrupts mit sei (was schon mal eine schwachsinnige 
Idee ist. Zuerst werden alle Sourcen konfiguriert und erst dann werden 
die Interrupts freigegeben)
Dann aktivierst du den externen Interrupt. Seine Defaulteinstellung ist: 
Interrupt an aktive Low. Den Fall hast du, der Pin IST low.
Und erst dann konfigurierst du den Interrupt auf Edge Detection.


Wie gesagt: Es ist ein Frage der Reihenfolge, in der Dinge konfiguriert 
und aktiviert werden.

> Einziges Problem ist, dass ich den Taster
> drücke und erst beim auslassen der Interrupt auslöst. Ist auch
> klar, da ich auf steigende Flanke programmiert habe.

Wo ist das Problem?
Konfiguriere den Interrupt auf fallende Flanke und er löst beim Drücken 
der Taste aus.

von Christian (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Du aktivierst die Interrupts mit sei (was schon mal eine schwachsinnige
> Idee ist. Zuerst werden alle Sourcen konfiguriert und erst dann werden
> die Interrupts freigegeben)

Wie würdest du das Programm verändern, damit es mit dem ext. Pulldown 
funktioniert? Bitte den Code in die richtige Reihenfolge setzen, da ich 
nicht weiß wie ich den Code verändern soll.

Danke für deine Bemühungen

von Christian (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wo ist das Problem?
> Konfiguriere den Interrupt auf fallende Flanke und er löst beim Drücken
> der Taste aus.

Das habe ich auch gemacht, muss aber den GND schalten.
Ich möchte aber +5V schalten.

von Karl H. (kbuchegg)


Lesenswert?

Christian schrieb:
> Karl heinz Buchegger schrieb:
>> Du aktivierst die Interrupts mit sei (was schon mal eine schwachsinnige
>> Idee ist. Zuerst werden alle Sourcen konfiguriert und erst dann werden
>> die Interrupts freigegeben)
>
> Wie würdest du das Programm verändern, damit es mit dem ext. Pulldown
> funktioniert? Bitte den Code in die richtige Reihenfolge setzen, da ich
> nicht weiß wie ich den Code verändern soll.

Ach komm.
Selber nachdenken. Nur so lernst du.

Wenn das Ziel ist:
  Wasserrohr mit neuem Wasserhahn ist an die Hauptversogung
  angeschlossen und der neu installierte Wasserhahn ist geschlossen,
  welches ist dann die richtige Reihenfolge

  * zuerst Rohr anschliessen
    dann Wasserhahn an Rohr schrauben
    dann Wasserhahn zudrehen

  * zuerst Hahn zudrehen
    dann Rohr anschliessen
    dann Hahn an Rohr schrauben

  * zuerst Hahn schliessen
    dann Hahn an Rohr schrauben
    dann Rohr anschliessen

  * zuerst ...

In alle Fällen landest du beim selben End-Ergebnis. Aber nur in einem 
der Fälle findest du keine überflutete Wohnung vor.

Ich denke ich habe in der ersten Antwort genug Hinweise gegeben, wie die 
zeitliche Entwicklung in deinem Programm ist und wie es zum Effekt 
kommt.

von Christian (Gast)


Lesenswert?

@Karl heinz Buchegger

Danke für die Tipps. War nur ein simpler Fehler.
Einfach das SREG nach der Konfiguration einschalten , wie du beschrieben 
hast.
1
 
2
GICR |= (1<<INT0);   
3
MCUCR |= (1<<ISC01)|(1<<ISC00); 
4
SREG |= (1<<7);


Danke nochmal

von Karl H. (kbuchegg)


Lesenswert?

Christian schrieb:
> Danke für die Tipps. War nur ein simpler Fehler.
> Einfach das SREG nach der Konfiguration einschalten , wie du beschrieben
> hast.
>
> GICR |= (1<<INT0);
> MCUCR |= (1<<ISC01)|(1<<ISC00);

umdrehen.
Zuerst konfigurieren
dann einschalten

> SREG |= (1<<7);

Dafür gibst sei()


Gewöhn dir die Reihenfolge an:
Zuerst werden die Dinge auf Arbeitsbedingungen eingestellt,
dann wird scharf geschaltet. Eventuell löscht man auch vor dem 
Scharfschalten noch einmal mögliche Interrupt-Flags, die sich 
zwischendurch angesammelt haben könnten, während die Konfiguration noch 
nicht vollständig war (und die daher auch Fehlalarme sein können, weil 
der µC auf ein "falsches Interruptereignis reagiert hat).

Nur James Bond springt mit dem Fallschirm in der Hand aus dem Flugzeug. 
Alle anderen stellen zuerst die Konfiguration her (schnallen sich den 
Fallschirm um) ehe sie auf scharf gehen (aus dem Flugzeug springen).

von Thomas B. (escamoteur)


Lesenswert?

Macht man bei Kondomen ja auch so ;-)

Sorry, konnte grad nciht wiederstehen ;-)

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.