Forum: Mikrocontroller und Digitale Elektronik PIN Change Interrupt Code klappt nicht


von Huber M. (michael_h784)


Lesenswert?

Hallo,

ich würde gerne einen Pinchange Interrupt auslösen ( eine led soll 
leuchten und wieder aus) um besser zu verstehen was das genau ist. Habe 
folgenden Code dazu geschrieben, aber irgendwie bringe ich ihn nicht zum 
laufen. Was mache ich den hier falsch?

grüsse huber

ich benütze;

Attiny24a
Atmelstudio6.0 mit original Avr isp mk2

/*
 * Attiny24A_test.c
 *
 * Created: 05.08.2016 11:23:30
 *  Author: Huber
 */

#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(PCINT1_vect)
{
  PORTA|= (1<<PA0);
  _delay_ms(1000);
  PORTA &= ~(1<<PA0);


}

int main(void)
{   //Ausgänge festlegen
  DDRA|= (1<<PA0);
  //Eingänge festlegen pullups
  PORTA|= (1<<PA1);

  //Interrupt Service Routine PCINT eintellen
  GIFR|= (1<<PCIF0);
  PCMSK0|= (1<<PCINT1);
  sei();

  while(1)
    {


    }
}

von Mitlesa (Gast)


Lesenswert?

Huber M. schrieb:
> GIFR|= (1<<PCIF0);

GIFR ist ein Flag-Register, da gibt es nichts zum Einstellen,
nur die IRQ Flags werden hier gelöscht und/oder abgefragt.

Was du einstellen willst/sollst ist das GIMSK (INT0) und das
MCUCR (Interrupt Sense Control Bits).

von Huber M. (michael_h784)


Lesenswert?

Mahlzeit,

nein, ich wollte schon gezielt die PCINT nutzen. Um zu verstehen was ich 
mit denen anfangen kann. Oder für was man diese benützt. Denn vom lesen 
alleine verstehe ich es einfach nicht. Ich bräuchte irgend ein beispiel. 
Denn int0 das kann ich, das sind ja externe interrups. Wie gesagt die 
PCINT verstehe ich nicht.

danke huber

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Huber M. schrieb:
> nein, ich wollte schon gezielt die PCINT nutzen.

 Dann must du die auch erlauben, dass versuchte dir Mitlesa in seinem
 Beitrag zu erklären.
1
  //Interrupt Service Routine PCINT einstellen
2
  PCMSK0 |= (1<<PCINT1);        //* PCINT auf PA.1 erlaubt
3
  GIMSK |= (1<<PCIE0);          //* PA.0 - PA.7 PCINT erlaubt
4
  sei();
 Und du darfst natürlich nicht mehr am PA.1 wackeln, denn selbst als
 Ausgang wird PA.1 einen Interrupt auslösen.

von Hosenmatz (Gast)


Lesenswert?

Nun, da hat mitlesa leider einen Fehler gemacht. Es handelt sich nicht 
um das Bit namens "INT0" sondern das Bit namens "PCIEO".

Das GIFR brauchst Du nicht zu setzen. Das dient dazu das Interrupt-Flag 
zurückzusetzen, falls der Interrupt mal aufgetreten ist. Das braucht man 
aber bis auf Ausnahmefälle nicht selbst zu tun, da es, wie im Datenblatt 
steht, selbsttätig zurückgesetzt wird, sobald die Interrupt-Routine 
angesprungen wird.

Aber das steht alles im Datenblatt.

Selbst wenn Du daraus nicht entnehmen kannst, wozu es gut ist, solltest 
Du aber die Funktionsweise erkennen können. In einer Bedienungsanleitung 
eines Autos steht ja auch nur, wie es zu bedienen ist, nicht was man 
damit machen kann oder soll.

Du solltest Du auch angewöhnen, genau zu beschreiben, was nicht 
funktioniert. Was geschieht und was stattdessen geschehen soll. Das 
hilft bei der Fehlersuche ungemein.

Und noch eins: Auch wenn es in Deinem Fall nur eine Rolle spielt, wenn 
Interrupts in kürzeren Abständen als 1s auftreten, solltest Du delays in 
Interrupt-Routinen vermeiden. In diesem Fall nur zu Übungszwecken, aber 
Du kannst ja mal die Interrupts in kurzen Abständen auslösen, dann 
siehst Du, das Du Probleme bekommst.

von Huber M. (michael_h784)


Lesenswert?

Moing,

so sieht der abgeänderte Code jetzt aus. Und, wenn jetzt irgend eine 
Veränderung an PCINT1 mittels Taster auftritt, soll PA0, 1sec. lang 
leuchten, und danach wieder ausgehen. Es tut sich aber gar nichts. Und 
wenn ich das richtig übersetzt habe, dann löst jede Veränderung an PCINT 
7-0 ein interrupt aus oder?

-die LED ist Ordnungsgemäß an PA0 angeschlossen
-der Taster an PA1(schaltet PA1 gegen GND). Und war testweise auch an 
andere pins. Es müsste doch eigentlich funktionieren?







/*
 * Attiny24A_test.c
 *
 * Created: 05.08.2016 11:23:30
 *  Author: Huber
 */

#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(PCINT1_vect)
{
  PORTA|= (1<<PA0);
  _delay_ms(1000);
  PORTA &= ~(1<<PA0);


}

int main(void)
{   //Ausgänge festlegen
  DDRA|= (1<<PA0);
  //Eingänge festlegen pullups
  PORTA|= (1<<PA1);

   //Interrupt Service Routine PCINT einstellen
  PCMSK0 |= (1<<PCINT1);        //* PCINT auf PA.1 erlaubt
  GIMSK |= (1<<PCIE0);          //* PA.0 - PA.7 PCINT erlaubt
  sei();

  while(1)
    {


    }
}

von Peter D. (peda)


Lesenswert?

Huber M. schrieb:
> ISR(PCINT1_vect)

Huber M. schrieb:
> GIMSK |= (1<<PCIE0);

Die Freigabe muß zum Handler passen.

von Sascha W. (sascha-w)


Lesenswert?

Huber M. schrieb:
> Moing,
>
> so sieht der abgeänderte Code jetzt aus. Und, wenn jetzt irgend eine
> Veränderung an PCINT1 mittels Taster auftritt, soll PA0, 1sec. lang
> leuchten, und danach wieder ausgehen. Es tut sich aber gar nichts. Und
> wenn ich das richtig übersetzt habe, dann löst jede Veränderung an PCINT
> 7-0 ein interrupt aus oder?
nein,
Im PCMSKx Register legst du fest welche der zugeordneten 8 Pins einen 
INT auslösen kann. Im GIMSK wiederum musst du festlegen welche Gruppe 
von PCINTs einen INT auslösen dürfen. Die ISR gibts immer nur für jede 
Gruppe, deshalb muss die auch die Nummer aus dem entspechenden PCMSK 
haben.
Solange du aus einer 8'er Gruppe genau einen Pin freigibst verhält sich 
die ISR genau wie bei INT0 o. INT1. Gibst du mehrere frei musst du in 
der ISR erst noch herausfinden welcher Pin den INT ausgelöst hat.

Wenn du für PA1 also  PCINT1 in PCMSK*0* setzt, und PCIE*0* im GISMK 
setzt und dann den richtigen INT PCINT0_vect nimmst, dann sollte es 
auch funktionieren.

Sascha

von Huber M. (michael_h784)


Lesenswert?

danke, ok, an PCINT1 wird jetzt ein interrupt ausgelöst. An den anderen 
nicht. Aber müsste es jetzt nicht egal sein an welchen (PCINT 7-0)ich 
den Taster anschliesse. Es müsste doch jetzt an jeden pin ein interrupt 
ausgelöst werden ?

von M. K. (sylaina)


Lesenswert?

Und gewöhne dir bitte ganz schnell ab, _delay_ms() in einer ISR zu 
benutzen. Das ist ein ganz böser Fehler.

von M. K. (sylaina)


Lesenswert?

Huber M. schrieb:
> Es müsste doch jetzt an jeden pin ein interrupt
> ausgelöst werden ?

Nein, nur die Pins, die du mittels PCMSK0 definiert hast, lösen einen 
Interrupt der Gruppe PCINT0_vect aus. Hast du nur Pin 1 definiert werden 
die Pins 0, 2-x keinen Interrupt der Gruppe auslösen.

von Huber M. (michael_h784)


Lesenswert?

ps, war wohl mit der antwort zu schnell, danke jetzt glaube ich habe ich 
es verstanden.

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.