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
> Kann mir da einer weiterhelfen?
Zuerst mal ist Zeile 42 in deinem Code falsch...
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 | }
|
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...
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 ?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.