mikrocontroller.net

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


Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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

#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) {          

    
  
sei();  // Globales Interrupt Enable Flag setzen
   
         
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);

   while(1) {             

   /* "leere" Schleife*/;
   }   

   /* wird nie erreicht */
   return 0;
}

Autor: Resetter (Gast)
Datum:

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

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while(1)
   {
    volatile ("nop");
   }

Autor: Daniel V. (danielv)
Datum:

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

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

Autor: sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Daniel V. (danielv)
Datum:

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

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was für ein µC ist es?
Welche Hardware?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?
#define INT0_vect                     _VECTOR(1)
#define INT1_vect                     _VECTOR(2)                 

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du keine externen Widerstände hast dann:

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

Autor: sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Daniel V. (danielv)
Datum:

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

Autor: sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein.
Ein Port bleibt solange gesetzt bis er zurückgesetzt wird.

Autor: sebastian (Gast)
Datum:

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

Autor: Daniel V. (danielv)
Datum:

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

Autor: Marco S (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Paul H. (powl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gegen prellen hilft ein 10N kerko parallel zum taster

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ich weiß auch alles besser (Gast)
Datum:

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

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das GIMSK heißt beim ATmega16

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

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: ich weiß auch alles besser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Resetter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo in Deiner Entwiklungsumgebung hast Du überall ATmega16 eingetragen?

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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
#define INT0_vect                     _VECTOR(1)
#define INT1_vect                     _VECTOR(2)
schmeiß raus.
Die sind im io.h definiert, wenn das Target stimmt.


Peter

Autor: ich weiß auch alles besser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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". ;-)

Autor: ich weiß auch alles besser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Axel R. (axelr) Flattr this
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Daniel V. (danielv)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.