Forum: Mikrocontroller und Digitale Elektronik Nach einer Interrupt Routine wird der PORT zurückgesetzt


von Daniel V. (danielv)


Lesenswert?

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
}

von Resetter (Gast)


Lesenswert?

Deine while Schleife wird eventuell wegoptimiert.
Damit fängt der µC immer wieder von vorne an.

von Resetter (Gast)


Lesenswert?

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

von Daniel V. (danielv)


Lesenswert?

Das ist es nicht gewesen. Habe zu Testzwecken folgende Zeile eingebaut:
1
temp1=temp1+temp;

Dies hat nicht funktioniert habe dann einen Compilerfehler erhalten
while(1)
   {
    volatile ("nop");
   }

von sebastian (Gast)


Lesenswert?

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

von Resetter (Gast)


Lesenswert?

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;
}

von Daniel V. (danielv)


Lesenswert?

Ja der Interrupt wird durch einen Taster ausgelöst. Laut Datenblatt 
werden die beiden Interrupts mit Steigender Flanke getriggert.

von Resetter (Gast)


Lesenswert?

Was für ein µC ist es?
Welche Hardware?

von Simon K. (simon) Benutzerseite


Lesenswert?

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)

von Resetter (Gast)


Lesenswert?

Wenn Du keine externen Widerstände hast dann:

DDRD  = 0x00;
PORTD = 0xFF; // PullUps einschalten

von sebastian (Gast)


Lesenswert?

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

von Daniel V. (danielv)


Lesenswert?

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)

von Daniel V. (danielv)


Lesenswert?

Das Temp habe ich global gemacht, da ich eigentlich in beiden Routinen 
drauf zugreifen wollte. So langsam verzeweifel ich an dem AVR :-(

von sebastian (Gast)


Lesenswert?

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

von Daniel V. (danielv)


Lesenswert?

ja aber auch da wird der port nur ganz kurz gesetzt und dann wieder 
zurückgesetzt. ich vermute das wenn ich ports im interrupt setze, das 
diese dann nur für die dauer des interrupts gültig sind. kann das sein?

von Resetter (Gast)


Lesenswert?

Nein.
Ein Port bleibt solange gesetzt bis er zurückgesetzt wird.

von sebastian (Gast)


Lesenswert?

Nein, der PORT müsste gesetzt bleiben, dann stimmt was anderes nicht...

von Daniel V. (danielv)


Lesenswert?

Hat denn einer von euch die Möglichkeit mein Porg mal zu testen?
Wäre echt super.

von Marco S (Gast)


Lesenswert?

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.

von Daniel V. (danielv)


Lesenswert?

Hallo Marco,

ja da gebe ich dir recht. Aber ich habe noch ein Grundsätzliches 
Problem. Und zwar wird auch bei INT0 der PortC nicht dauerhaft gesetzt. 
Es blinkt immer nur kurz auf.

von Paul H. (powl)


Lesenswert?

gegen prellen hilft ein 10N kerko parallel zum taster

von Daniel V. (danielv)


Lesenswert?

es sollte kein Problemn mit dem Prellen sein, da ich das Board von 
pollin benutze. Ich sehe ja auch das der Ausgang den Zustand wechselt, 
jedoch nur für kurze Zeit

von Peter D. (peda)


Lesenswert?

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

von Daniel V. (danielv)


Lesenswert?

Hallo Peter,

Ich benutze den ATMEGA16, vielleicht hast du ja durch diese Info die 
Möglichkeit das zu testen. Wäre echt super. An die Fuses habe ich auch 
schon gedacht. Kann man diese so ohne weiteres ändern?

von Peter D. (peda)


Lesenswert?

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

von ich weiß auch alles besser (Gast)


Lesenswert?

Vielleicht noch ein
temp = 0;
vor dem while (1)
?

von Daniel V. (danielv)


Lesenswert?

Hallo Peter,

doch ich benutze den AtmEGA 16 auf dem POLLIN BOard. Bei mir wird der 
Code ohne Probleme compeliert. Ich compeliere mit AVR Studio 4 und 
übertrage dann mit Ponyprog und hatte bisher auch nie Probleme

von Resetter (Gast)


Lesenswert?

Das GIMSK heißt beim ATmega16

GICR |=(1<<INT0)|(1<<INT1);

von Daniel V. (danielv)


Lesenswert?

Das GIMSK heißt beim ATmega16

GICR |=(1<<INT0)|(1<<INT1);

ich habe dies nun abgeändert, jedoch ändert sich leider nichts an dem 
verhalten. Hat noch jemand eine Idee? Kann es an den Fuses liegen?

von ich weiß auch alles besser (Gast)


Lesenswert?

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.

von Resetter (Gast)


Lesenswert?

Wo in Deiner Entwiklungsumgebung hast Du überall ATmega16 eingetragen?

von Daniel V. (danielv)


Lesenswert?

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?

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von ich weiß auch alles besser (Gast)


Lesenswert?

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". ;-)

von ich weiß auch alles besser (Gast)


Lesenswert?

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...

von Axel R. (Gast)


Lesenswert?

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?

von Daniel V. (danielv)


Lesenswert?

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 :-)

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.