Forum: Mikrocontroller und Digitale Elektronik Interrupt wird zwei mal aufgerufen


von Rush .. (rush)


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

von Justus S. (jussa)


Lesenswert?

> Kann mir da einer weiterhelfen?

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

von Rush .. (rush)


Lesenswert?

Hahahahah ;-)

1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
volatile char mode;
5
volatile char locked = 0;
6
7
#define    DDR      DDRD
8
#define    PULLUP    PORTD
9
#define    OUT      PORTD
10
#define    IN      PIND
11
#define    DIPSWT1    PD6
12
#define    DIPSWT2    PD4
13
#define    PHOTO    PD2      // INT0
14
#define    MIC      PD3      // INT1
15
#define    TRIGGER    PD0
16
#define    FOCUS    PD1    
17
18
// Für externen Interrupt INT0 und INT1 ; Licht- und Soundtrigger
19
20
void trig_lock(void)
21
{
22
  cli();
23
  OUT &=~ (1<<FOCUS);
24
  _delay_ms(500);
25
  OUT &=~ (1<<TRIGGER);
26
  _delay_ms(500);
27
  OUT |= (1<<TRIGGER);
28
  _delay_ms(500);
29
  OUT |= (1<<FOCUS);
30
  _delay_ms(500);
31
  locked = 0;
32
  sei();
33
}
34
35
ISR(INT1_vect)
36
{
37
  trig_lock();
38
}
39
40
41
void init(void)
42
{
43
  DDR &=~ (1<<DIPSWT1) | (1<<DIPSWT2);
44
  PULLUP |= (1<<DIPSWT1) | (1<<DIPSWT2);
45
  DDR |= (1<<TRIGGER) | (1<<FOCUS);
46
  OUT |= (1<<TRIGGER) | (1<<FOCUS);
47
  sei();
48
49
/*  DDRD |= (1<<PD5) | (1<<PD0);    //LEDs
50
  PORTD |= (1<<PD5) | (1<<PD0);
51
  PORTD &=~ (1<<PD2);        // Phototransistor
52
  MCUCR |= (1<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10);  // INT0, INT1 rising edge
53
  GIMSK |= (1<<INT0) | (1<<INT1); // enable Interrupts on INT0 and INT1
54
  sei();  // enable global interrupts*/
55
}
56
57
void main(void)
58
{
59
init();
60
61
62
  while (1)
63
    {
64
    if ((!(IN & (1<<DIPSWT1))) && (!(IN & (1<<DIPSWT2))))    {mode = 0;}  // Sound with Mirror-Lockup
65
    if ((IN & (1<<DIPSWT1)) && (!(IN & (1<<DIPSWT2))))    {mode = 1;} // Light with Mirror-Lockup
66
    if ((IN & (1<<DIPSWT1)) && (IN & (1<<DIPSWT2)))      {mode = 2;} // Light without Mirror-Lockup 
67
    if ((!(IN & (1<<DIPSWT1))) && (IN & (1<<DIPSWT2)))    {mode = 4;} // Sound without Mirror-Lockup
68
    
69
    if (mode == 0)
70
      {
71
      switch (mode){
72
        case 0:
73
        MCUCR |= (1<<ISC11) | (1<<ISC10);    // enable INT1
74
            MCUCR &=~ (1<<ISC01) | (1<<ISC00);  // disable INT0
75
           GIMSK |= (1<<INT1);          // enable Interrupt on INT1
76
           GIMSK &=~ (1<<INT0);          // disable Interrupt on INT0
77
        break;
78
      case 1:
79
        MCUCR &=~ (1<<ISC11) | (1<<ISC10);  // disable INT1
80
            MCUCR |= (1<<ISC01) | (1<<ISC00);    // enable INT0
81
           GIMSK &=~ (1<<INT1);          // disable Interrupt on INT1
82
           GIMSK |= (1<<INT0);          // enable Interrupt on INT0
83
        break;
84
        }
85
    /*  if (locked == 0)
86
        {
87
        OUT &=~ (1<<FOCUS);
88
        _delay_ms(500);
89
          OUT &=~ (1<<TRIGGER);
90
        _delay_ms(500);
91
        OUT |= (1<<TRIGGER);
92
        _delay_ms(500);
93
        OUT |= (1<<FOCUS);
94
        locked = 1;
95
      }*/
96
      
97
    }
98
    
99
      
100
    
101
    }
102
}

von Justus S. (jussa)


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

von Rush .. (rush)


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 ?

von Justus S. (jussa)


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.html#faq_intbits

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.