Forum: Mikrocontroller und Digitale Elektronik Türkontakt an Atmega8


von Dieter (Gast)


Lesenswert?

Hallo,

ich habe einen Türkontakt an PD2 (INT0) eines Atmega8 gegen GND hängen.
Ich möchte, dass ein Interrupt ausgelößt wird, wenn die Tür auf oder 
zu geht.

Aus dem Datenblatt des Atmega8 habe ich entnommen, dass mit "MCUCR |= 
1<<ISC00;" "any logical change on INT0" einen Interrupt auslößt.

Folgender Code funktioniert trotzdem nicht (es wird nur ein Interrupt 
ausgelößt wenn die Tür aufgeht und er wird weiter ausgelößt solange die 
Tür auf ist, was auch unerwünscht ist):
1
int main(void)
2
{
3
        DDRD = 0x00;
4
        GIMSK |= 1<<INT0;
5
        MCUCR |= 1<<ISC00;
6
        sei();
7
        while(1) {
8
                if( GIFR & (1 << INTF0)) {
9
                        uart_puts("Gerade ist die Tür auf oder zu gegangen\n");
10
                }
11
        }
12
13
        return 0;
14
}
15
16
        
17
}

Ich habe keine Ahnung was falsch ist und finde leider auch nichts im 
Netz.
Es würde mich freuen wenn mir jemand helfen könnte.

Gruß,   Dieter

von Jörg G. (joergderxte)


Lesenswert?

Lass' mal "sei()" weg -- und wenn's dann geht, lies nochmal nach was 
Interrupt bedeutet...

scnr, Jörg

von Andreas W. (geier99)


Lesenswert?

Jörg G. schrieb:
> Lass' mal "sei()" weg -- und wenn's dann geht, lies nochmal nach was
> Interrupt bedeutet...
>
> scnr, Jörg

aber dann muss er auch das Interupt-Flag selber löschen.

von Jörg G. (joergderxte)


Lesenswert?

> aber dann muss er auch das Interupt-Flag selber löschen.
Ist besser als der Reset wegen der fehlenden ISR...

von Dieter (Gast)


Lesenswert?

Ohne das sei() geht leider garnichts.

Gruß,   Dieter

von Andreas W. (geier99)


Lesenswert?

Dieter schrieb:
> Ohne das sei() geht leider garnichts.

das hatte ich schon fast befürchtet. Da wahrscheinlich die serielle 
Ausgabe auch Interrupts verwendet.

Also, mach das mit dem Interrupt richtig: :-)
1) ISR funktion für INT0 schreiben, in der Du einfach ein Flag setzt 
dass die Tür betätigt wurde

2) dieses Flag fragst Du in Deiner Hauptschleife ab (auch das 
Zurücksetzen dieses Flags dann nicht vergessen)

von Dieter (Gast)


Lesenswert?

Danke Andreas für die Antwort.

Genau das hatte ich auch schon versucht, ging aber auch nicht (wenn ich 
dich richtig verstanden habe)

Du meinst so?
1
volatile uint8_t flag;
2
3
ISR(INT0_vect)
4
{
5
        flag=1;
6
}
7
8
int main(void)
9
{
10
        DDRD = 0x00; // Eingang
11
        GIMSK |= 1<<INT0;
12
        MCUCR |= 1<<ISC00;
13
        uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
14
        sei();
15
16
        while(1) {
17
                if(flag == 1) {
18
                 uart_puts("Tür auf oder zugegangen\n");
19
                 flag=0;
20
                 }
21
        }
22
23
        return 0;
24
}
Das macht genau das gleiche wie mein Code oben.

Gruß,   Dieter

von Bernd K. (viper)


Lesenswert?

Hallo.

Kenn mich mit C nicht so gut aus, mehr mit ASM, aber so wie du das 
gemacht hast, hast das gleiche als wenn du FLAG nicht abfragen würdest, 
weil solange die Tür auf ist setzt er FLAG=1.

Du musst das Setzten des Flags nur einmal ausführen, wenn die Tür auf 
gemacht wird und dann solange überspringen bis die Tür wieder zu ist.

Aber warum willste das Ganze mit nem Interruptpin machen, das geht doch 
auch super mit nem normalen Eingangspin ?

CU
Bernd

von Andreas W. (geier99)


Lesenswert?

Dieter schrieb:
> Danke Andreas für die Antwort.
>
> Du meinst so?

Vom Prinzip her ja, dann werde ich wohl mal mein STK 500 rausholen 
müssen und es mal selbst probieren.

von Andreas W. (geier99)


Lesenswert?

Hmm,

ich habs jetzt bei mir mal nem ATMega16 probiert und da funktioniert es 
problemlos. Hier ist mal mein Code (Achtung die Syntax ist leicht etwas 
anderst, da ich den CodeVision AVR C verwende).
1
volatile unsigned char ucFlag=0;           // Statusflag für INT0 ist aufgetreten
2
3
4
// External Interrupt 0 service routine
5
interrupt [EXT_INT0] void ext_int0_isr(void)
6
{
7
// Place your code here
8
  if(ucFlag<255) ucFlag++;
9
}
10
11
void main(void)
12
{
13
.....
14
// Port D initialization
15
PORTD=(1<<PD2);    // Pull Up für INT0 (PD2) aktivieren
16
DDRD= (1<<PD4);    // Debug LED an Port D4
17
18
// External Interrupt(s) initialization
19
// INT0: On
20
// INT0 Mode: Any change
21
// INT1: Off
22
// INT2: Off
23
GICR  |= (1<<INT0);           
24
MCUCR  = (1<<ISC00); 
25
MCUCSR = 0x00;
26
GIFR   = (1<<INTF0);
27
.......
28
// Global enable interrupts
29
#asm("sei")
30
31
while (1) {
32
    if(ucFlag) {
33
        ucFlag--;
34
        printf("Tür auf oder zugegangen\n");
35
    }
36
    #asm("wdr")
37
};  // end while
38
}

Einziger Unterschied, was mir noch zu Dir auffällt ist, dass ich für den 
INT0 sicherheitshalber noch den  PullUp aktiviert habe.
Ausserdem, bist Du Dir sicher, dass das Register MCUCR bei Dir mit 0x00 
intialisiert wurde?( Falls nicht dann schreib lieber: MCUCR = 1<<ISC00; 
)

Ansonsten, simuliere Dein Programm einfach mal im AVR-Studio da kann man 
schön sehen, woran es habert.

Bye
 Andreas

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.