Forum: Mikrocontroller und Digitale Elektronik Interrupts mega168


von Werner H (Gast)


Lesenswert?

Hallo!
möchte gerne einen Interrupt auslösen und die ISR starten wenn ich einen 
Taster an PINC1 (PCINT9-Eingang) drücke. Soweit so gut, nur folgender 
Code funktioniert nicht (Es läuft nur die Hauptschleife immer durch, 
beim Tasterdruck passiert nichts) :
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define F_CPU 8000000UL
5
#include <util/delay.h>
6
7
ISR(INT1_vect)
8
{
9
  while(1)
10
  {
11
    DDRD=0xFF;
12
                _delay_ms(50);
13
    DDRD=0x00;
14
                _delay_ms(50);
15
  }
16
}
17
18
int main(void)
19
{
20
  DDRD = 0b11111111;
21
  PORTD = 0b00000000;
22
  DDRC = 0b11000000;
23
  PORTC = 0b00111111;
24
  
25
  PCICR = 0b00000010; //PCMSK1 freischalten
26
  PCMSK1 = 0b00000010; //PCINT9 (PC1-PIN) an Taster
27
  EICRA = 0b00001100; //Steigende Taktflankenerkennung
28
  
29
  sei();
30
  
31
  while(1)
32
  {
33
    DDRD=0xFF;
34
                _delay_ms(1000);
35
    DDRD=0x00;
36
                _delay_ms(1000);
37
  }
38
}

Habe ich evtl noch ein paar Register nicht oder falsch konfiguriert?

Gruß,
Werner

von Rainer B. (katastrophenheinz)


Lesenswert?

Der Interrupt, den du brauchst, heißt PCINT1, nicht INT1.
Und EICRA hat damit nichts zu tun.

Ist dir der Unterschied zwischen INTx und PCINTx, x=0,1,2 bekannt?
Guck mal ins Manual falls nicht.

Und du solltest auf keinen Fall Endlos-Schleifen in Interrupt-Routinen 
legen,
sondern diese so kurz wie möglich halten. D.h. in der ISR nur ein Flag 
setzen und dieses dann in einer Endlosschleife in main() auswerten.

So wie oben wird das nicht funktionieren.

von OldMan (Gast)


Lesenswert?

Deine ISR wird, falls sie denn aufgerufen wird, nie beendet!
Ein
1
 while (1)
 macht man nicht in einer ISR!

Die Registerinitialisierungen habe ich jetzt nicht kontrolliert.

von Oliver S. (oliverso)


Lesenswert?

Allgemein ist es immer gut, für die Konfiguration der Kontrollregister 
die Bitnamen zu verwenden, in der Art
1
PCICR |= (1<<PCMSK1);

Ob du die richtigen Bits in deinem Programm gesetzt hast, musst du schon 
selber rausfinden.

Oliver

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Werner H schrieb:
> Habe ich evtl noch ein paar Register nicht oder falsch konfiguriert?

EIMCR Flankenwahl gilt nur für die beiden INT0 und INT1 externen 
Interrupts, der Pinchange Interrupt wird, wie der Name sagt, bei jedem 
Polaritätswechsel ausgelöst -

Werner H schrieb:
> ISR(INT1_vect)
> {
>   while(1)
>   {
>     DDRD=0xFF;
>                 _delay_ms(50);
>     DDRD=0x00;
>                 _delay_ms(50);
>   }
> }

Du schreibst eine ISR für INT1, möchtest aber PCINT1, das musst du 
ändern. Ausserdem wird diese ISR nie wieder verlassen, und das möchtest 
du auch nicht. Also:
1
ISR(PCINT1_vect) {
2
// meine PCINT1 Routine ohne while(1)
3
4
5
}

: Bearbeitet durch User
von Werner H (Gast)


Lesenswert?

Rainer B. schrieb:
> Ist dir der Unterschied zwischen INTx und PCINTx, x=0,1,2 bekannt?
> Guck mal ins Manual falls nicht.

Ja, ich kann mich aber irren: INTx ist der Vektor der auf ein bestimmte 
Adresse zeigt und PCINTx ist der Eingangspin des uCs, mit dem ich 
wahlweise einen INT0 oder INT1 auslöse. Kann mich aber irren, mein 
Englisch ist eher mäßig...

Die while(1)-Schleife ist nur zum testen drin ob die ISR überhaupt 
aufgerufen wird. Das ist aber nicht der Fall.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ich meinte natürlich nicht EIMCR, sondern auch EICRA.

Werner H schrieb:
> Ja, ich kann mich aber irren: INTx ist der Vektor der auf ein bestimmte
> Adresse zeigt und PCINTx ist der Eingangspin des uCs, mit dem ich
> wahlweise einen INT0 oder INT1 auslöse. Kann mich aber irren, mein
> Englisch ist eher mäßig...

Du irrst dich. Der Mega168 stellt für jede 'Bank' von PC Interrupts 
einen Vektor zur Verfügung, plus die beiden für INT0 und INT1:
Kapitel 12.2:

Table 12-1.     Reset and interrupt vectors in ATmega48.
Vector no.     Program address     Source Interrupt definition
1 0x000 RESET
External pin, power-on reset, brown-out reset and watchdog system reset
2 0x001 INT0 External interrupt request 0
3 0x002 INT1 External interrupt request 1
4 0x003 PCINT0 Pin change interrupt request 0
5 0x004 PCINT1 Pin change interrupt request 1
6 0x005 PCINT2 Pin change interrupt request 2
7 0x006 WDT Watchdog time-out interrupt
8 0x007 TIMER2 COMPA Timer/Counter2 compare match A
9 0x008 TIMER2 COMPB Timer/Counter2 compare match B
10 0x009 TIMER2 OVF Timer/Counter2 overflow
11 0x00A TIMER1 CAPT Timer/Counter1 capture event
12 0x00B TIMER1 COMPA Timer/Counter1 compare match A
13 0x00C TIMER1 COMPB Timer/Coutner1 compare match B
14 0x00D TIMER1 OVF Timer/Counter1 overflow
15 0x00E TIMER0 COMPA Timer/Counter0 compare match A
16 0x00F TIMER0 COMPB Timer/Counter0 compare match B
17 0x010 TIMER0 OVF Timer/Counter0 overflow
18 0x011 SPI, STC SPI serial transfer complete
19 0x012 USART, RX USART Rx complete
20 0x013 USART, UDRE USART, data register empty
21 0x014 USART, TX USART, Tx complete

: Bearbeitet durch User
von Fritz G. (fritzg)


Lesenswert?

Du solltest den Ausgang mit PORTD schalten, nicht DDRD.

von Werner H (Gast)


Lesenswert?

Matthias Sch. schrieb:
> Du irrst dich. Der Mega168 stellt für jede 'Bank' von PC Interrupts
> einen Vektor zur Verfügung, plus die beiden für INT0 und INT1:

Sorry, das habe ich überlesen. Danke für eure Tipps, jetzt läuft es.

Gruß,
Werner

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.