Nach einer Interrupt Routine wird der PORT zurückgesetzt

OP #659884
Hallo Zusammen,

ich habe ein Problem mit meinem AVR. Wenn ich während eines Externen 
Interrupts das Ports setze, dann werden diese nach Verlassen ser 
Interruptroutine zurückgesetzt. Wenn ich den untenstehenden Quell Code 
im AVR Studio simulieren bleibt der Port jedoch gesetzt? Kann mir jemand 
helfen? Was ich erreichen möchte, ist das immer wenn ein Interrupt 
ausgelöst wurde die Ausgänge an Port C verändert werden. Möchte damit 
eine Art Freigabe Schaltung für einen Sensor realisieren. Ist es 
überhaupt möglich die Ports innerhalb der Interrupts dauerhaft zu 
setzen, so das diese Ports dann auch weiter im Hauptprogramm benutzt 
werden können?

Vielen Dank im Voraus

1
#include <avr/io.h>         
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
#define INT0_vect                     _VECTOR(1)
5
#define INT1_vect                     _VECTOR(2)
6

7
volatile uint8_t temp; 
8

9

10
ISR(INT0_vect) 
11
{
12
   PORTC = 0x01;
13
}
14
  
15
ISR(INT1_vect) 
16
{
17
        switch (temp)
18
  {
19
  case 0:
20
  PORTC = 0x01;
21
  temp++;
22
  break;
23

24
  case 1:
25
  PORTC = 0x02;
26
  temp++;
27
  break;
28

29
  case 3:
30
  PORTC = 0x03;
31
  temp=0;
32
  break;
33
  }
34
}
35

36
int main (void) {          
37

38
    
39
  
40
sei();  // Globales Interrupt Enable Flag setzen
41
   
42
         
43
DDRC  = 0xff;  // Port C als Output
44
PORTC = 0x00;  
45
DDRD  = 0x00;  // Port D als Input
46

47

48
MCUCR |= (1<<ISC01)|(1<<ISC00)|(1<<ISC10)|(1<<ISC11);
49
GIMSK |=(1<<INT0)|(1<<INT1);
50

51
   while(1) {             
52

53
   /* "leere" Schleife*/;
54
   }   
55

56
   /* wird nie erreicht */
57
   return 0;
58
}
Gast
1
MCUCR |= (1<<ISC01)|(1<<ISC00)|(1<<ISC10)|(1<<ISC11);

womit wird der Interrupt ausgelöst ? Taste ?
Ich habe keine Lust in Dattenblatt zu schauen, ich meine aber, daß Du 
Levelinterrupt geschaltet hast und kein Flankeninterrupt.

Gruß Sebastian
Gast
Versetze das   sei();  // Globales Interrupt Enable Flag setzen
wie unten.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define INT0_vect                     _VECTOR(1)
#define INT1_vect                     _VECTOR(2)

volatile uint8_t temp;


ISR(INT0_vect)
{
   PORTC = 0x01;
}

ISR(INT1_vect)
{
        switch (temp)
  {
  case 0:
  PORTC = 0x01;
  temp++;
  break;

  case 1:
  PORTC = 0x02;
  temp++;
  break;

  case 3:
  PORTC = 0x03;
  temp=0;
  break;
  }
}

int main (void) {

DDRC  = 0xff;  // Port C als Output
PORTC = 0x00;
DDRD  = 0x00;  // Port D als Input


MCUCR |= (1<<ISC01)|(1<<ISC00)|(1<<ISC10)|(1<<ISC11);
GIMSK |=(1<<INT0)|(1<<INT1);

sei();  // Globales Interrupt Enable Flag setzen

   while(1)
   {
    asm volatile ("nop");
   }

   /* wird nie erreicht */
   return 0;
}
Persönliche Seite
Daniel V. wrote:
> Ja der Interrupt wird durch einen Taster ausgelöst. Laut Datenblatt
> werden die beiden Interrupts mit Steigender Flanke getriggert.

Taster an Interrupts zu hängen ist generell eine schlechte Idee, da 
Taster nicht direkt von "Auf" nach "Zu" gehen, wenn man draufdrückt, 
sondern noch eine Weile "prellen".

Hier hilft eine Hardware-Entprellung mit RC-Tiefpass oder auf Interrupts 
verzichten und mit Peter Danneggers Bullet-Proof-Taster-Polling zu 
arbeiten.

PS: Was soll eigentlich das hier?
1
#define INT0_vect                     _VECTOR(1)
2
#define INT1_vect                     _VECTOR(2)
Gast
Ja sorry, hast recht, Du triggerst auf steigender Flanke.
Dann prellt Deine Taste, wie simon schon gesagt hat.
Warum machst Du temp global ?
besser wäre es, temp als static in der ISR zu deklarieren

Gruß Sebastian
OP
Ich habe es nun ausprobiert wenn ich das sei() umsetzte, trotzdem keine 
Änderung. Über die Beschaltung der Interrupts muss ich mir im ersten 
Schritt denke ich keine Sorgen machen. Ich benutze die auf dem Pollin 
Board befindlichen Taster dür die Interrupts. Dort befinden sich Pullup 
Widerstände und ein Kondensator zur Entprellung drauf. Ich sehe ja auch 
das der Port kurz geschaltet wird nur dann erlischt er wieder. Aber er 
soll ja auch nachdem die Interrupt routine verlassen wurde gesetzt 
bleiben.
Geht das überhaupt das?

Die Zeilen habe ich aus dem Tutorial aauf dieser Seite

#define INT0_vect                     _VECTOR(1)
#define INT1_vect                     _VECTOR(2)
Gast
Funktioniert denn die Taste, die an INT0 hängt ?
hier sollte der PORT bei 0x01 bleiben, egal, ob die Taste prellt, oder 
nicht.
Und lösche den Quatch mit
#define INT0_vect                     _VECTOR(1)
#define INT1_vect                     _VECTOR(2)

Gruß Sebastian
Gast
Hallo.

switch(temp): Nach dem Verlassen von "case 1:" ist temp = 2. Allerdings 
werden die Fälle für temp == 2 sowie 4 <= temp <= 255 nicht erfasst.
Daniel V. wrote:
> Hat denn einer von euch die Möglichkeit mein Porg mal zu testen?

Ne, geht nicht.

Bin kein Hellseher, kann also nicht riechen, welchen AVR Du hast.


Einige haben ne M103 Fuse, die schickt Deinen Stack in den Wald.


Peter
Daniel V. wrote:

> Ich benutze den ATMEGA16

stimmt nicht:

X.C: In function 'main':
X.C:49: error: 'GIMSK' undeclared (first use in this function)
X.C:49: error: (Each undeclared identifier is reported only once
X.C:49: error: for each function it appears in.)


Peter
Gast
Wie sind INT0 und INT1 extern beschaltet?
Egal, was Besserwisser dazu meinen, ich habe schon
"Mitnahmeeffekte" bei benachbarten I/Os beobachtet.
Vielleicht noch ein "PORTD = 0xff;" ?
Schadet bestimmt nicht.
OP
Nur bei Anlage des Projektes habe ich im Auswahlfenster auf der Linken 
Seite Simulation und auf der rechten Seite ATMEGA16 ausgewählt. Nach dem 
ich dann das Prog compiliert habe schicke ich es mit Ponyprog auf den 
AVR. In Ponyprog habe ich auch ATMEGA16 ausgewählt.

@ich weiss auch alles besser:

Meine INT0 und INT 1 sind über das POLLIN Board mittels eines PULLUP 
widerstandes und eines Kondensators zum entprellen beschaltet. ICh sehe 
ja auch kurzzeitig das der Interrupt ausgeführt wird. von daher sollte 
es kein Pegelproblem sein?
Persönliche Seite
Daniel V. wrote:
> Meine INT0 und INT 1 sind über das POLLIN Board mittels eines PULLUP
> widerstandes und eines Kondensators zum entprellen beschaltet. ICh sehe
> ja auch kurzzeitig das der Interrupt ausgeführt wird. von daher sollte
> es kein Pegelproblem sein?

Keine Ahnung ob es bei dir das Problem sein kann, aber generell schließt 
man Taster nicht an externe Interrupts an. Wenn die externe Entprellung 
aber korrekt dimensioniert ist, sollte das nichts machen.

Wo "siehst" du denn, dass der Interrupt ausgeführt wird? Weißt du wie 
schnell ein Taster prellen kann? Das kann man mit einer LED und dem 
menschlichen Auge nicht wahrnehmen. (Du siehst ja auch nicht, dass der 
Schalter für deine Zimmerbeleuchtung prellt). Hierfür bräuchte man schon 
ein Oszilloskop.

Das Problem daran ist aber, dass der Mikrocontroller so schnell ist, 
dass er das Prellen des Taster genau "mitbekommt". Aus seiner Sicht 
gesehen, ist das Prellen des Tasters sau-lahm.
Daniel V. wrote:
> Hallo Peter,
>
> doch ich benutze den AtmEGA 16 auf dem POLLIN BOard. Bei mir wird der
> Code ohne Probleme compeliert.

Dann hast Du nicht den ATmega16 als Target definiert, der hat kein 
GIMSK.

Bei nem falschen Target stürzt das Programm natürlich ab.

Und die Zeilen
1
#define INT0_vect                     _VECTOR(1)
2
#define INT1_vect                     _VECTOR(2)
schmeiß raus.
Die sind im io.h definiert, wenn das Target stimmt.


Peter
Gast
Ich tippe auch auf Tastenpreller.
Ändere mal Deine INT1-isr spasseshalber so ab, dass
sie in acht Durchläufen die acht PortC-I/Os einzeln
bedient. Oszilloskop dran und "nur ein Ping". ;-)
Gast
Ist der ICP1-Eingang nach außen geführt? Vielleicht auch
einen Versuch wert, mit aktiviertem noise canceler.
Es geht natürlich nichts über einen ordentlichen Tasten-
entpreller. Ich persönlich taste Tasteneingänge über Timer-
interrupt ab, und entprelle per Software.

Feuer frei...
Gast
Hi,
setz doch mal PORTC auf 255 beim Start.
Wenn der AVR neustartet, müssten dann alle LEDs an sein. Dann sieht man 
besser, wenn es einen neustart gab.
Oder Du lässt Dir über das MCUSR die Resetquelle auf PORTC ausgeben.

int main (void) {

DDRC  = 0xff;  // Port C als Output
PORTC = 0xff; <--- zum Test auf "FF" setzen
DDRD  = 0x00;  // Port D als Input

Das Target sollte schon richtig eingestellt sein, sonst gehts nicht. 
JTAG ist aus?
OP
Hallo Axel,

die Idee mit dem PORT C auf FF zu setzen hat gezeigt, das der AVR einen 
Neustart macht. Und siehe da jetzt habe ich auch den Fehler gefunden. In 
meiner Entwicklungsumgebung war trotz auswahl des ATMEGA16 unter Device 
noch ATMEGA32 eingetragen. Ich denke mal das war ein typischer 
Anfängerfehler.
Trotzdem ein riesen Dankeschön an alle!!! ICh Verspreche Besserung :-)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 19 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.