Forum: Mikrocontroller und Digitale Elektronik Pin Change Interrupt


von Andreas R. (alienworkshop)


Lesenswert?

Guten Tag Zusammen,

konnte leider nach länger suche über eine Suchmaschine und auch direkt 
hier nichts finden.

Bin gerade im moment dabei eine Digitaluhr für mein Auto zu bauen. Die 
Originale ist defekt und ich wollte mich mal wieder mit uC beschäftigen 
also wollte ich das als einstiegsprojekt verwenden.

Die Uhr an sich mit 7-Segment ist alles klar das läuft mit externem 16 
Mhz Quarz. Ich möchte nun die Zündleitung dafür verwenden einen 
Interrupt zu schalten. Ich Teste erstmal direkt mit 5v der Schaltugn 
selbst also spielt die Spannung von 12V im Auto auf dem Testaufbau keine 
Rolle. Wenn die Zündung aus ist soll der uC keine Ausgaben auf der 
7-Segment machen und wenn die Zündung an ist dann schon. Desweitern 
möchte ich auch den Lichtschalter abgreifen und die Helligkeit der 
7-Segment dimmen sobald licht an ist, damit man eben Nachts nicht 
geblendet wird.

Ich verwende einen ATMega168. Als Entwicklungsumgebung verwende ich 
Atmel Studio 6.1.

Als Eingang für diese beiden Schaltungen möchte ich PC5 und PC4 
verwenden und zwar als PCINT13 und PCINT12.

Quellcode nach meinem Gedächnis, sitze nicht vor dem Laptop im Moment.

DDRC = 0b00000000;
PORTC = 0b00000111; // die 1 sind für 3 Taster die noch am Port C hängen

Pin Change interupt aktivieren
PCICR |= (1 << PCIE1);

Pin Change Mask entsprechend für die Zwei Pins setzen.
PCMSK |= (1 << PCINT13) | (1 << PCINT12);

Interruptroutine

ASR (PCINT1_vect)

hier wird ein Bit getoggelt das ich in er Main Routine abfrage und wenn 
es gesetzt ist wird in den idle_sleep mode geschalten, ansonsten wird 
ein "display update" durchgeführt,sprich das anzeigen der uhrzeit über 
die 7-Segent. Das mit der Beleuchtung ist erstmal aussen vor, ist ja das 
gleiche Prinzip.

Mit einem 5V Input will ich also nun diese Interrupts auslösen und damit 
das Bit-Toggeln. Leider passiert rein garnichts.

Setzte ich den Pin auf PortC entsprechend auf 1 funktioniert das ganze 
und es schaltet in den sleep mode.

Könnt Ihr mir sagen ob meine Denkweise überhautp richtig ist oder kann 
ih gar keine 5v quelle als input benutzten um damit einen Interrupt über 
pin change auszulösen?

Danke euch schonmal.

Gruss Andy

von Karl H. (kbuchegg)


Lesenswert?

Andreas Rosengart schrieb:

> Rolle. Wenn die Zündung aus ist soll der uC keine Ausgaben auf der
> 7-Segment machen und wenn die Zündung an ist dann schon. Desweitern
> möchte ich auch den Lichtschalter abgreifen und die Helligkeit der
> 7-Segment dimmen sobald licht an ist, damit man eben Nachts nicht
> geblendet wird.

Und wozu brauchst du da einen Pin Change Interrupt?
Schaltest du die Zündung innerhalb von ein paar µs ein bzw. aus?

Für derartige Eingangsabfragen ist ein Interrupt erstens Perlen vor die 
Säue und zweitens viel komplizierter als notwendig.

Frag in der Hauptschleife die beiden Pins ab, meinetwegen im halbe 
Sekunden Abstand und gut ists.

von Andreas R. (alienworkshop)


Lesenswert?

Interrupt weil Controller im Sleep Idle Mode während die Zündung aus 
ist?

Der Interrupt für den Timer zählt ja die Zeit weiter während der 
Controller im Idle Mode ist und damit ja garnichtsmehr macht bis ein 
interrupt kommt, sprich die Hauptroutine garnichmther durchlaufen wird?

von Thomas E. (thomase)


Lesenswert?

Andreas Rosengart schrieb:
> Interrupt weil Controller im Sleep Idle Mode während die Zündung aus
> ist?
>
> Der Interrupt für den Timer zählt ja die Zeit weiter während der
> Controller im Idle Mode ist und damit ja garnichtsmehr macht bis ein
> interrupt kommt, sprich die Hauptroutine garnichmther durchlaufen wird?

Idle ist ein höchstens drittklassiger Sleepmode, der kaum Strom spart, 
da der Takt weiterläuft. Wenn die Uhr es schafft, die Batterie im Auto 
leerzusaugen, ist das Problem allerdings nicht die Uhr sondern die 
Batterie.

Aber wenn schon:

ISR(PCINTx_vect)
{
 PCICR = 0;
}

Und dann fragst du in der main ganz geruhsam die Eingänge ab.
Wenn die Zündung aus ist, schaltest du die PCINTs wieder ein und gehst 
in Sleep.

Wenn du es ordentlich machen willst, guckst du dir den asynchronen Mode 
des Timer2 an.

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Rosengart schrieb:
> Interrupt weil Controller im Sleep Idle Mode während die Zündung aus
> ist?
>
> Der Interrupt für den Timer zählt ja die Zeit weiter während der
> Controller im Idle Mode ist


exakt.
Und was hindert dich daran, in genau diesem Interrupt den du für die 
Zeitweiterschaltung sowieso benötigst dann auch noch die Pins 
abzufragen.

Genau. Nichts.

PS: in
1
int main()
2
{
3
  ....
4
5
  while( 1 )
6
  {
7
    ....
8
9
    sleep();    // schlafen legen
10
11
    ....
12
  }
13
}
dreht die Hauptschleife nach jedem Aufwachen (und das tut sie für die 
Zeitweiterschaltung) genau eine Runde. D.h. deine Hauptschleife WIRD 
laufend ausgeführt. Der µC geht ja nicht nach dem Abarbeiten der ISR 
automatisch wieder schlafen.
Wird sleep() aufgerufen, dann geht der AVR in den eingestellten Sleep 
Mode. Wird er aufgeweckt, dann wird in deinem Fall dann eben die ISR 
abgearbeitet aber danach kommt das Programm aus dem sleep() zurück, 
arbeitet das Programm weiter durch, bis es auf den nächsten sleep() 
stösst und erst dann legt sich der AVR wieder zur Ruhe.

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.