Forum: Mikrocontroller und Digitale Elektronik Interrupt-Problem


von Matthias Drexler (Gast)


Lesenswert?

Hallo

Ich habe ein ATmega32 Prototype Board.
und da wollte ich einen ganz einfachen Interrupt machen aber da hängt 
sich der Controller immer auf.

  MCUCR |= (1<<ISC01);
  MCUCR &= ~(1<<ISC00);
  GIMSK |= (1<<INT0);

ISR (INT0_vect)
{
  rprintf("AT+CMSS=3\r\n");
}

kann mir da jemand behilflich sein?

mfg
Matthias Drexler

von Falk B. (falk)


Lesenswert?

Siehe Interrupt.

MfG
Falk

von Klaus (Gast)


Lesenswert?

Üblicherweise ist der Aufruf von komplexen Funktionen in Interrupts zu 
vermeiden. Dafür gibt es im Einzelfall natürlich bestimmte Gründe. Diese 
gezielt darzulegen ist hier aber nicht möglich, da Details fehlen. Falls 
die Ausgabe mittels rprintf selbst Interrupts benutzt, bestehen 
vielfältige Möglichkeiten, warum das nicht funktioniert. Nicht zuletzt 
die Tatsache, dass, während eine Interruptroutine abgearbeitet werden, 
keine weiteren Interrupts behandelt werden können. (Was nichts damit zu 
tun hat, das jeweils ein Interrupt zumindest in dem jeweiligen 
Interrupt-Flag gespeichert wird).

Ich empfehle Dir, in der Interrupt Routine lediglich eine Variable zu 
setzen, dies Flag in einer Endlos-Schleife in der Funktion main 
abzufragen und falls es gesetzt ist, die Ausgabe zu machen.

von Matthias Drexler (Gast)


Lesenswert?

Hallo Klaus

Wenn ich zum beispiel den PORTB auf high setze so dass dann LED´s 
brennen hängt er ich auch auf.....

welche details würden dir denn fehlen?

mfg
Matthias

von Hans (Gast)


Lesenswert?

Poste das Programm!

von Klaus (Gast)


Lesenswert?

Abgesehen vom Programm selbst wäre es interessant zu wissen, woran Du 
denn genau merkst, das der uC sich "aufhängt". Gerade in diesem Bereich 
gibt es sehr viele Missverständnissse.

von Matthias Drexler (Gast)


Lesenswert?

wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD 
anzeige und meine leds einfach stehen.

von Klaus (Gast)


Lesenswert?

>wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD
>anzeige und meine leds einfach stehen.

Aha. Nun gut. Poste bitte den Code.

von Klaus (Gast)


Lesenswert?

Vielleicht wäre es gut, wenn Du auch mal schreibst, was Du an 
Messmitteln hast, die Schaltung, Deine Vorkenntnisse (formal und/oder 
autodidaktisch angeeignete).

von Matthias Drexler (Gast)


Lesenswert?

#include <avr/io.h>
#include "global.h"     // include our global settings
#include "i2cmaster.h"   // Auskommentieren, falls nicht benötigt...
#include "lcd.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "string.h"
#include "timer.h"
#include <stdlib.h>
#include <stdio.h>
#include "usart.h"

#define USE_LCD 1    // 1 Falls LCD verwendet wird

void init(void)
{
  wdt_disable();    // Watchdog ausschalten

  // Port B initialisieren
  DDRB= 0xFF;       // alle 8 pins sind als Ausgang geschaltet


  // Port A initialisieren
  DDRA= 0x00;       // alle 8 pins sind als Eingänge geschaltet


  PORTB= 0x00;    // Alle unteren Pins sind low

  timer0Init();      /*   Mit diesem Befehl wird die include-Datei timer 
initialisiert,
            die uns u.a. den Befehl timerPause() zur Verfügung stellt.
            */
  i2c_init();       // Initialisierung des I2C-Busses

  sei();        // Interrupts zulassen (für timer.c wichtig)



#if USE_LCD
  lcd_init(LCD_DISP_ON);
#endif

  lcd_clrscr(); // LCD löschen



  MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus
  MCUCR &= ~(1<<ISC00);
  GIMSK |= (1<<INT0);  //Interrupt_1 einschalten

  uartInit();     // initialize the UART (serial port)
  uartSetBaudRate(9600); // serielle Schnittstelle auf 19200 Baud setzen
  rprintfInit(uartSendByte);


  lcd_puts("\nStarte Programm!");
  timerPause(3000);


}



int main (void)
{


  init();


    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
    {
    }


  rprintf("AT+CMSS=5\r\n");
  timerPause(1000);


  lcd_clrscr(); // LCD löschen

  lcd_puts("Programm bereit!");
  timerPause(3000);

  while(1)
  {
  ..............
  .................
  }

}

ISR (INT0_vect)
{

    rprintf("AT+CMSS=3\r\n");

}

von Matthias Drexler (Gast)


Lesenswert?

messmittel is a Multimeter.
schaltung is a bisschen schwer zu posten und was meinst du mit 
vorkenntnisse?

von Klaus (Gast)


Lesenswert?

Bitte vollständigen, compilierbaren Code posten. Falls Du das aus 
irgendwelchen Gründen nicht willst, dann reduziere den Code, aber auf 
jeden Fall so, dass das Problem noch auftritt.

In dem geposteten Code ist jedenfalls, bis auf die fehlerhafte 
Verwendung einer komplexen Funktion mit vermutlich 
Interrupt-Abhängigkeiten, nichts weiter erkennbar. Ausserdem werden hier 
nirgendwo Ports verändert, so das diese Aussage

>wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD
>anzeige und meine leds einfach stehen.

nicht nachvollziehbar ist.

Im Zweifel, was wie gepostet und beschrieben werden sollte, siehe: 
http://www.mikrocontroller.net/articles/Netiquette

Ausserdem fehlen noch die Angaben zu:

>Vielleicht wäre es gut, wenn Du auch mal schreibst, was Du an
>Messmitteln hast, die Schaltung, Deine Vorkenntnisse (formal und/oder
>autodidaktisch angeeignete).

von jonas biensack (Gast)


Lesenswert?

MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus
  MCUCR &= ~(1<<ISC00);

Müsste da nicht entweder zweimal ISC01 oder zweimal ISC00 hin?

Wie schnell nach erscheinen von Starte Prorgramm löst du den Interrupt 
aus? wenn der noch in der timerpause funktion hängt, geht dass nicht?

gruß Jonas

von jonas biensack (Gast)


Lesenswert?

////////////////////////////////////////////////
//INTerrupt konfigurieren


MCUCR  |= (1<<ISC01); // Int auslösen bei fallender Flanke
EIMSK  |= (1<<INT0);  // External Interrupt 0 Enable PIN PD2


//Globale Interrupts einschalten
sei();

Gerade kopiert aus einem anderen Thread, sollte funktionieren...


gruß Jonas

von Klaus (Gast)


Lesenswert?

Das hat sich jetzt überschnitten. Bin ein langsamer Schreiber:

>messmittel is a Multimeter.
>schaltung is a bisschen schwer zu posten und was meinst du mit
>vorkenntnisse?

Was ist das Problem beim Posten der Schaltung?

Vorkenntnisse: Angaben darüber welche Kenntnisse Du hast. Das kann man 
auf verschiedene Weise beschreiben: z.B. Formal: Studium Bachelor 
Informatik, Lehre Informationselektroniker, Informell: Autodidaktisch 
ca. 10 Jahre Erfahrung etcpp.

Anders gefragt: Was von dem folgende hast Du schonmal realisiert. D.h. 
den Code vollständig selbst geschrieben. Nicht ob Du einzelne Teile 
aus Tutorials kopiert hast.

1. LED blinken lassen
2. Delay mit Timern
3. Tastenentprellung
4. Tasten- oder LED-matrix
5. LCD Ansteuerung
6. RS232 Kommunikation

Es geht nur darum einen Eindruck zu bekommen, was man voraussetzen kann.

von Klaus (Gast)


Lesenswert?

jonas biensack schrieb:

>>  MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus
>>  MCUCR &= ~(1<<ISC00);

>Müsste da nicht entweder zweimal ISC01 oder zweimal ISC00 hin?

Wohin müsste das zweimal. Bei Triggern auf fallender Flanke können ISC01 
und ISC00 jedenfalls nicht auf den selben Wert gesetzt werden.

>MCUCR  |= (1<<ISC01); // Int auslösen bei fallender Flanke

Dazwischen gibt es keine Unterschied, solange ISC00 im Programmlauf 
sonst nicht manipuliert wird. Der Default-Wert von ISC00 ist ohnehin 0.

>EIMSK  |= (1<<INT0);  // External Interrupt 0 Enable PIN PD2

Das Register EIMSK gibt es beim ATMega32 garnicht. Genauso wie das im 
Code vorkommende Register GIMSK.

Dagegen wird in dem Codebruchstück GICR nicht geändert. Deswegen Frage 
nach dem vollständigen, compilierbaren Code. Genauso wie nach den 
Vorkenntnissen.

von Klaus (Gast)


Lesenswert?

Alles in allem drängt sich der Verdacht auf, das beim Compilieren die 
falsche CPU gesetzt ist, sonst gäbe es Fehlermeldungen.

von Matthias Drexler (Gast)


Lesenswert?

#include <avr/io.h>
#include "global.h"     // include our global settings
#include "i2cmaster.h"   // Auskommentieren, falls nicht benötigt...
#include "lcd.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "string.h"
#include "timer.h"
#include <stdlib.h>
#include <stdio.h>
#include "usart.h"


#ifndef F_CPU
  /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
   F_CPU im Makefile definiert werden, eine nochmalige Definition
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
   #ifndef/#endif

   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
   verwendet wird und dort eine andere, nicht zur Hardware passende
   Taktrate eingestellt ist: Dann wird die folgende Definition
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
   noch nicht definiert: */
  #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 
14756000"
  #define F_CPU 14756000UL  // Systemtakt in Hz - Definition als 
unsigned long beachten
                         // Ohne ergeben sich unten Fehler in der 
Berechnung
  #endif

  #define BAUD 9600UL      // Baudrate

  // Berechnungen
  #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
  #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
  #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 
= kein Fehler.

  #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu 
hoch!
  #endif

void init(void)
{

  wdt_disable();    // Watchdog ausschalten


  DDRD &= ~(1<<PD2);

  // Port B initialisieren
  DDRB= 0xFF;       // alle 8 pins sind als Ausgang geschaltet


  // Port A initialisieren
  DDRA= 0x00;       // alle 8 pins sind als Eingänge geschaltet


  PORTB= 0x00;    // Alle unteren Pins sind low (Ruhestellung)

  timer0Init();      /*   Mit diesem Befehl wird die include-Datei timer 
initialisiert,
            die uns u.a. den Befehl timerPause() zur Verfügung stellt.
            */
  i2c_init();       // Initialisierung des I2C-Busses

  sei();        // Interrupts zulassen (für timer.c wichtig)



#if USE_LCD
  lcd_init(LCD_DISP_ON);
#endif

  lcd_clrscr();

MCUCR  |= (1<<ISC01); // Int auslösen bei fallender Flanke
GICR  |= (1<<INT0);  // External Interrupt 0 Enable PIN PD2

//  MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus
//  MCUCR &= ~(1<<ISC00);
//  GIMSK |= (1<<INT0);  //Interrupt_1 einschalten


  uartInit();     // initialize the UART (serial port)
  uartSetBaudRate(9600); // serielle Schnittstelle auf 19200 Baud setzen
  rprintfInit(uartSendByte);


  lcd_puts("\nStarte Programm!");
  timerPause(3000);


} // Ende init


int main (void)
{

  init();

while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich
    {
    }


rprintf("AT+CMSS=5\r\n");
timerPause(1000);

lcd_clrscr();
lcd_puts("Programm bereit!");
timerPause(3000);


while(1)
{

lcd_clrscr();

PORTB = (1<<PB0);
timerPause(300);
lcd_clrscr();
lcd_puts("\xFF\xFF\xFF\xFF\xFF");


PORTB = (1<<PB1);
timerPause(300);
lcd_clrscr();
lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");


PORTB = (1<<PB2);
timerPause(300);
lcd_clrscr();
lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF") 
;


PORTB = (1<<PB3);
timerPause(300);
lcd_clrscr();
lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x 
FF\xFF\xFF\xFF\xFF");
}
}


ISR (INT0_vect)
{

  PORTB = 0xFF;
  timerPause(100);
  PORTB = 0x00;
  timerPause(100);
  PORTB = 0xFF;
  timerPause(100);

//    rprintf("AT+CMSS=3\r\n");

}

von Matthias Drexler (Gast)


Lesenswert?

ich bin angehender Techniker in Kommunikationstechnik.
und das ist eigentlich nur mein hobby schaltungen zu programmieren und 
zu bauen.

von Matthias Drexler (Gast)


Lesenswert?

und das mit dem GICR funktioniert auch nicht

von Klaus (Gast)


Lesenswert?

>und das mit dem GICR funktioniert auch nicht

Was heisst, "es funktioniert" nicht?

Es gibt einen "richtigen" Weg und einen "falschen". Rumprobieren hilft 
Dir nicht weiter. Erwarte auch nicht von jeder einzelnen Maßnahme für 
sich, das sie gleich eine Verbesserung bringt.
Wenn Du klagst das Dein Auto nicht fährt und Du auf einen Rat hin Benzin 
nachfüllst und es immer noch nicht fährt, dann entfernst Du ja auch 
nicht das Benzin, "weil es nicht geholfen hat". Es kommt oft vor, das 
mehrere Ursachen gemeinsam eine Funktion verhindern.

Abgesehen davon:

Du hättest eigentlich Fehlermeldungen erhalten müssen. Was ist mit der 
Einstellung der CPU?

Delays in interruptroutinen sind genauso "falsch" wie Aufruf von 
rprintf.

Bitte mach es so, wie schon beschrieben. Flag setzen und in main 
abfragen.

von Klaus (Gast)


Lesenswert?

>Es kommt oft vor, das mehrere Ursachen gemeinsam eine Funktion verhindern.

Das sollte vielmehr heissen:

Es kommt oft vor, das mehrere Ursachen jeweils für sich eine Funktion 
verhindern.

von Klaus (Gast)


Lesenswert?

Ausserdem lässt sich der Code schon wegen einfachen syntaktischen 
Fehlern nicht kompilieren.

In der Zeile:
1
while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich

fehlt das Ende des Kommentars. Auch in den nachfolgenden Zeilen taucht 
das fehlende */ nicht auf.

Bitte gib Dir Mühe wirklich compilierbaren Code zu posten.

Am besten nimm die Datei(en) und kopiere sie in ein anderes Verzeichnis 
und mach ein neues Projekt im AVRStudio (vorausgesetzt das verwendest 
Du). Tu so als wenn Du wir wärst und nur das hättest, was hier gepostet 
wurde.

von Klaus (Gast)


Lesenswert?

Füge ich den Kommentar ein, dann kommen noch mehr Fehlermeldungen:

rm -rf Drexler.o  Drexler.elf dep/* Drexler.hex Drexler.eep Drexler.lss 
Drexler.map
avr-gcc  -mmcu=atmega32 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT Drexler.o 
-MF dep/Drexler.o.d  -c  ../Drexler.c
../Drexler.c:2:55: error: global.h: No such file or directory
../Drexler.c:3:69: error: i2cmaster.h: No such file or directory
../Drexler.c:4:17: error: lcd.h: No such file or directory
../Drexler.c:8:19: error: timer.h: No such file or directory
../Drexler.c:11:19: error: usart.h: No such file or directory

von Klaus (Gast)


Lesenswert?

So. Jetzt habe ich mal was Anderes zu tun. Werde mich jetzt raushalten.

von Matthias Drexler (Gast)


Lesenswert?

Problem gelöst....
Danke mochmal allen.

mfg
Matthias Drexler

von Klaus (Gast)


Lesenswert?

Schön für Dich.

Was lerne ich also hier über Dich?

1. Es lohnt sich nicht Dir Fragen zu stellen. Du antwortest nicht oder 
erst nach Erklärung von Begriffen des eigentlichen Grundwortschatzes. 
Z.B. "Vorkenntnisse".
2. Du  postest keinen compilierbaren Code.
3. Du setzt Anregungen nicht um.
4. Auf Erklärungen reagierst Du nicht.
5. Wenn Du dann die Lösung findest, teilst Du sie nicht mit uns.

Toll. Da macht das helfen wirklich Spass. Bis zum nächsten Mal.

von Matthias Drexler (Gast)


Lesenswert?

1.habe ich gemacht. vielleicht nicht so schnell wie dir es gepasst 
hätte. und wenn mir deine fragen nicht eindeutig genug waren muss ich ja 
nachfragen.
2.ich habe es gepostet. 2mal.
3.wenn ich das nicht gemacht hätte würde es wahrscheinlich immer noch 
nicht gehen.
4.wie gesagt vielleicht nicht so schnell wie du es gerne haben würdest 
aber ich habe auch noch ein bisschen was anderes zu tun.
5.du bräuchtest nur zu fragen. es war die sache mit kein rprintf und 
timerPause im interrupt.
und 6. du besitzt nicht wirklich viel menschenkenntnis

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.