www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt wird zwei mal aufgerufen


Autor: Rush ... (rush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Attiny2313 mit AVR-GCC und AVR Studio.


Ich habe das Signal eines Elektretmikrofon über einen Hochpass (100n und 
220k) gejagt, das über einen LM358 und dann an den INT1 eines Tiny2313.

Nun möchte ich das Signal über einen Interrupt auswerten. Allerdings 
wird dieser manchmal zwei mal hintereinander aufgerufen.

Zum Test lasse ich einfach ein Feuerzeug klicken oder klatsch über dem 
Mic.
In der ISR habe ich Warteschleifen von insgesammt 2 Sekunden drin.

Warum wird die ISR manchmal zwei mal hintereinandern aufgerufen.
Habe schon versucht einfach die Kapazität des Hochpasses zu erhöhen, bin 
mittleriweile bei 2 uF angekommen und es bringt immer noch nichts?

Kann mir da einer weiterhelfen?

MFG, Rush

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann mir da einer weiterhelfen?

Zuerst mal ist Zeile 42 in deinem Code falsch...

Autor: Rush ... (rush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hahahahah ;-)

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile char mode;
volatile char locked = 0;

#define    DDR      DDRD
#define    PULLUP    PORTD
#define    OUT      PORTD
#define    IN      PIND
#define    DIPSWT1    PD6
#define    DIPSWT2    PD4
#define    PHOTO    PD2      // INT0
#define    MIC      PD3      // INT1
#define    TRIGGER    PD0
#define    FOCUS    PD1    

// Für externen Interrupt INT0 und INT1 ; Licht- und Soundtrigger

void trig_lock(void)
{
  cli();
  OUT &=~ (1<<FOCUS);
  _delay_ms(500);
  OUT &=~ (1<<TRIGGER);
  _delay_ms(500);
  OUT |= (1<<TRIGGER);
  _delay_ms(500);
  OUT |= (1<<FOCUS);
  _delay_ms(500);
  locked = 0;
  sei();
}

ISR(INT1_vect)
{
  trig_lock();
}


void init(void)
{
  DDR &=~ (1<<DIPSWT1) | (1<<DIPSWT2);
  PULLUP |= (1<<DIPSWT1) | (1<<DIPSWT2);
  DDR |= (1<<TRIGGER) | (1<<FOCUS);
  OUT |= (1<<TRIGGER) | (1<<FOCUS);
  sei();

/*  DDRD |= (1<<PD5) | (1<<PD0);    //LEDs
  PORTD |= (1<<PD5) | (1<<PD0);
  PORTD &=~ (1<<PD2);        // Phototransistor
  MCUCR |= (1<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10);  // INT0, INT1 rising edge
  GIMSK |= (1<<INT0) | (1<<INT1); // enable Interrupts on INT0 and INT1
  sei();  // enable global interrupts*/
}

void main(void)
{
init();


  while (1)
    {
    if ((!(IN & (1<<DIPSWT1))) && (!(IN & (1<<DIPSWT2))))    {mode = 0;}  // Sound with Mirror-Lockup
    if ((IN & (1<<DIPSWT1)) && (!(IN & (1<<DIPSWT2))))    {mode = 1;} // Light with Mirror-Lockup
    if ((IN & (1<<DIPSWT1)) && (IN & (1<<DIPSWT2)))      {mode = 2;} // Light without Mirror-Lockup 
    if ((!(IN & (1<<DIPSWT1))) && (IN & (1<<DIPSWT2)))    {mode = 4;} // Sound without Mirror-Lockup
    
    if (mode == 0)
      {
      switch (mode){
        case 0:
        MCUCR |= (1<<ISC11) | (1<<ISC10);    // enable INT1
            MCUCR &=~ (1<<ISC01) | (1<<ISC00);  // disable INT0
           GIMSK |= (1<<INT1);          // enable Interrupt on INT1
           GIMSK &=~ (1<<INT0);          // disable Interrupt on INT0
        break;
      case 1:
        MCUCR &=~ (1<<ISC11) | (1<<ISC10);  // disable INT1
            MCUCR |= (1<<ISC01) | (1<<ISC00);    // enable INT0
           GIMSK &=~ (1<<INT1);          // disable Interrupt on INT1
           GIMSK |= (1<<INT0);          // enable Interrupt on INT0
        break;
        }
    /*  if (locked == 0)
        {
        OUT &=~ (1<<FOCUS);
        _delay_ms(500);
          OUT &=~ (1<<TRIGGER);
        _delay_ms(500);
        OUT |= (1<<TRIGGER);
        _delay_ms(500);
        OUT |= (1<<FOCUS);
        locked = 1;
      }*/
      
    }
    
      
    
    }
}

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sei und cli haben in einer ISR nichts zu suchen, dass macht die schon 
von alleine... und delays in einer ISR sind ebenfalls ganz pöhse...

mach mal am Ende deiner ISR

GIFR = (1<<INTF1);

afaik wird das Flag ja am Anfang der ISR-Routine gelöscht, da deine 
jetzt so extrem lang ist, kann es ja passieren, dass ein zweiter 
Interrupt auftritt, durch den sofort nach dem wiederenablen der 
Interrupts die ISR wieder aufgerufen wird...

Autor: Rush ... (rush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wunderbar, hat geklappt. Allesdings heisst es in meinem Fall EIFR und 
nicht GIFR.

Kann es sein dass im DS ein Schreibfehler vorliegt?!

Dort steht nämlich geschrieben:

Bit 7 – INTF1: External Interrupt Flag 1
When an edge or logic change on the INT1 pin triggers an interrupt 
request, INTF1 becomes set (one). If the I-bit in SREG and the INT1 bit 
in GIMSK are set (one), the MCU will jump to the corresponding Interrupt 
Vector. The flag is cleared when the interrupt routine is executed. 
Alternatively, the flag can be cleared by writing a logical one to it. 
This flag is always cleared when INT1 is configured as a level 
interrupt.

Also auf Deutsch:
Bei einer logischen Pinänderung wird INTF1 auf eins gesetzt 
(Voraussetzung SREG etc.) Die MCU springt dann in den Interruptvecotr 
und wenn diese abgearbeitet wird wird INTF1 auf null gesetzt (cleared).

Alternativ kann das Bit manuell zurückgesetzt werden indem man eine 
logische EINS reinschreibt ?!?!?!

Eine eins setzt doch das Bit wie es in den ersten Zeilen heisst?!

Oder verstehe ich hier was falsch ?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rush ... wrote:
> Wunderbar, hat geklappt. Allesdings heisst es in meinem Fall EIFR und
> nicht GIFR.

sorry, hab aus Versehen ins Mega8 Datenblatt geschaut

> Alternativ kann das Bit manuell zurückgesetzt werden indem man eine
> logische EINS reinschreibt ?!?!?!
>
> Eine eins setzt doch das Bit wie es in den ersten Zeilen heisst?!

http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...

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.