Forum: Mikrocontroller und Digitale Elektronik Hilfe mit Interrupts


von Alex (Gast)


Lesenswert?

Hallo,
ich versuche seit einiger zeit in das interrupthandling auf meinem 
ATMEGA16 einzusteigen muss aber zugeben, dass ich den wald vor lauter 
bäumen nicht mehr sehe (auch im AVR-GCC Tutorial hier auf der seite).

Was ich möchte:
Mit AtMega16 und AVRStudio / GCC einen externen Interrupt behandeln. 
Dafür bietet der µC nach Datenblatt INT0 (PD2), INT1(PD3) und INT2(PB2) 
an.

Was ich verstanden habe:
Was interrupts ungefähr sind und wozu sie gut sind.

Was ich brauche:
Eigentlich nur einmal einen möglichst simplen --> Beispielcode <--, den 
ich 1zu1 anwenden kann, um dahinterzusteigen, was ich brauche und wie 
ich es verwende.
Mir ist klar, dass ich die interrupts mit sei(); global einschalte und 
mit cli(); global ausschalte.

Was folgt dann?

Ich sollte doch nach dem einschalten irgendwie die verknüpfung zwischen 
interrupt und auszuführender funktion (mit namen "SIGNAL 
(sig_interrupt0)" o.Ä.) herstellen?

Beispiel: Ich möchte an Pin PD2 durch einen einfachen Pegelwandel eine 
subroutine im programm des µC laufe lassen. Ich sehe ich vielen artikeln 
im internet unterschiedliche bezeichnungen, evtl abhängig vom compiler 
etc... und weiß daher nicht was ich brauche.

Ich hoffe, dass sich nicht wieder einige Menschen hier angegriffen 
fühlen dadurch, dass ich diese (wahrscheinlich schon oft gestellte) 
Anfängerfrage hier stelle - ich vermisse blos einfach ein 
Sourcecodebeispiel, mit dem ich auch etwas anfangen kann. Zu viele 
Flags, zu viele Bits in irgendwelchen Registern...

Vielen Dank für jegliche hilfe!

Grüße
Alex

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:

> Was ich verstanden habe:
> Was interrupts ungefähr sind und wozu sie gut sind.

Na, das ist doch schon mal was

> Was ich brauche:
> Eigentlich nur einmal einen möglichst simplen --> Beispielcode <--, den
> ich 1zu1 anwenden kann, um dahinterzusteigen, was ich brauche und wie
> ich es verwende.
> Mir ist klar, dass ich die interrupts mit sei(); global einschalte und
> mit cli(); global ausschalte.
>
> Was folgt dann?

Du brauchst

* Klarheit darüber, welcher Interrupt es überhaupt sein soll.
  Es gibt viele Interrupts. Einige hängen mit speziellen Pins am
  AVR zusammen, wieder andere mit speziellen Dingen bei Timern, wieder
  andere Interrupts beschäftigen sich zb mit speziellen Zuständen bei
  einer UART, etc.

  Du willst fürs erste einen Interrupt per Pin auslösen lassen, zb.
  den INT0 Pin

* Ein Interrupt an sich ist sinnlos, solange er nicht behandelt wird
  Je nachdem welcher Interrupt etwas auslösen soll, brauchst du einen
  eigenen Interrupt Handler, die ISR.
  Die für deinen INT0 Interrupt zuständige ISR, würde zb so aussehen
1
  ISR(INT0_vect)
2
  {
3
    /* Interrupt Code */
4
  }

  Alle Interrupt Handler werden mit ISR eingeleitet. In der Klammer
  steht der Name des ISR Handlers, der mit dem Interrupt Ereignis
  korrespondiert. Du willst den INT0. Daher heißt der Handler INT0_vect

* Nun kommt aber nicht einfach ein Interrupt so daher. Er muss
  freigegeben werden. Für den INT0 zuständig ist das Bit INT0 im
  Register GIMSK.
  Nur wenn dieses Bit auf 1 steht, löst das Ereignis auch tatsächlich
  einen Interrupt aus. Ereignisse treten ständig auf, daher muss man
  dem µC auch sagen: Interessiert mich oder interessiert mich nicht.

* Und dann braucht es noch die generelle Interrupt Freigabe mittels
  sei. sei/cli ermöglichen die gemeinschaftliche Stilllegung oder
  Freigabe aller Interrupts auf einmal.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
 
4
ISR(INT0_vect)       /* veraltet: SIGNAL(SIG_INTERRUPT0) */
5
{
6
    /* Interrupt Code */
7
}
8
9
int main()
10
{
11
  // der pin PD2 steht schon auf Eingang, da ist
12
  // also keine weitere Aktion notwendig
13
14
  // je nachdem welche Hardware da drann hängt, müsste man
15
  // ev. einen Pullup aktivieren
16
17
  //
18
  // den INT0 spezifisch freischalten
19
  //
20
  GIMSK |= ( 1 << INTO );
21
22
  //
23
  // und Interrupts generell freigeben
24
  //
25
  sei();
26
27
  //
28
  // ab jetzt ist alles scharf. Wenn am Eingang INT0 etwas passiert
29
  // wird die ISR INT0_vect aufgerufen.
30
  //
31
32
  while( 1 )
33
    ;
34
}

> Sourcecodebeispiel, mit dem ich auch etwas anfangen kann. Zu viele
> Flags, zu viele Bits in irgendwelchen Registern...

Da musst du durch.

von Alex (Gast)


Lesenswert?

wow herzlichen dank!
das heisst das "argument" (hier INT0_vect) von ISR ist der name des zu 
verwendenden interrupts und der muss nur einmal in der funktion und 
einmal beim bitsetzen angegeben werden - dann alle interrupts ein und 
alles läuft?

kleine fragen noch, dann bin ich absolut zufrieden ;)

Der Interrupthandler ISR ist also die funktion, die beim interrupt 
ausgeführt wird?
Wieso steht im Argument noch der anhang "_vect" und nicht nur INT0? Bei 
einem anderen Interrupt wäre das dann immer ähnlich zB INT2_vect etc?

Das sieht jetzt alles in meinem kopf schon viel besser aus. danke 
nochmal!

von Christopher G. (cbg)


Lesenswert?

Datasheet vom µC und avr-libc Manual lesen (zumindest die benötigten 
Teile).
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

von Alex (Gast)


Lesenswert?

Hallo, ich bekomme beim verwerten des codebeispieles oben von AVR Studio 
compiler ein "GIMSK undeclared" und "INT0 undeclared" - obwohl ich die 
avr/interrupt.h included habe.
Woran könnte das liegen?

von Oliver (Gast)


Lesenswert?

Das Codebeispiel passt nicht für einen Mega16. Bei dem heissen die 
Register und Bits anders. Aber mit etwas Datenblattstudium bekommst du 
das sicherlich hin.

Oliver

von ... (Gast)


Lesenswert?

Du hast vergessen "avr/io.h" zu includieren

von Alex (Gast)


Lesenswert?

hallo, avr/io.h ist includiert...
@oliver ja, genau das ist ja der punkt, ich versuche seit einiger zeit 
einfach mal ein funktionierendes beispiel auf meinem ATmega16 zum 
funktionieren zu bringen, an dem ich mich langhangeln kann. und 
natürlich stehts alles im datenblatt, aber eben auch viel mehr.. und 
deshalb habe ich momentan probleme...

von Alex (Gast)


Lesenswert?

um das etwas genauer zu fassen: auf seite 45 vom ATmega16 datenblatt 
finde ich "Table18" Reset and Interrupt Vectors.
Kleiner Ausschnitt:

Vector No.   Program Address   Source   Interrupt Definition

1            $000(1)           RESET    External Pin, Power-on Reset,
                                        Brown-out Reset, Watchdog Reset,
                                        and JTAG AVRReset
2            $002              INT0     External Interrupt Request 0
3            $004              INT1     External Interrupt Request 1
4            $006              TIMER2   COMP Timer/Counter2 Compare 
Match

Das hilft mir dann auch wieder nicht weiter, denn dass INT0 ein Externen 
Interrupt auslöst war mir bewusst und eine Liste mit Dingen, die mir aus 
den obigen erklärungen bekannt vorkommen vermisse ich...

von Karl H. (kbuchegg)


Lesenswert?

Im Datenblatt gibt es einen Abschnitt über die externen INterrupts 
(Kapitel 13). Dort ist dann alles zusammengefasst. Inklusive aller 
Register mit allen Konfigurationsbits.

Das Register heißt GICR

Hilft nichts. Du musst lernen mit dem Datenblatt umzugehen

von ... (Gast)


Lesenswert?

Alex schrieb:
> hallo, avr/io.h ist includiert...

Ja, Oliver war war beim Tippen schneller, ich beim Nachdenken ZU schnell 
:)

Das, was Du suchst steht im Datenblatt auf Seite 69 
(http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf).
Das Register heißt beim Mega16 "GICR".

von Alex (Gast)


Lesenswert?

Danke für die antworten, mein problem ist wohl hauptsächlich das 
registerverständnis..
ayway - GICR (statt GIMSK) und INT0 sind immernoch undeklariert, ich 
habe eingebunden

[c]#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>[c]

und benutze AVR Studio 4.

Das verwiesene Kapitel über externe Interrupts habe ich 
(wieder)gefunden, hatte es vorher auch gesehen aber wusste eben nicht, 
was damit anzufangen ist.. immerhin dämmert es mir langsam.. danke 
dafür.

von Oliver (Gast)


Lesenswert?

Alex schrieb:
> ayway - GICR (statt GIMSK) und INT0 sind immernoch undeklariert

Hast du auch den Mega16 im AVRStudio eingestellt?

Oliver

von Michael M. (Gast)


Lesenswert?

controller ist in den prjekt-optionen nicht eingestellt.

von Alex (Gast)


Lesenswert?

ja, die selben einstellungen wie immer (und da funzt alles) und zur 
sicherheit gerade noch einmal überprüft...

von Karl H. (kbuchegg)


Lesenswert?

Hast du den Code per Copy&Paste übernommen?

Wenn ja, da ist noch ein Tippfehler (im AVR Studio sieht man ihn)
da steht nicht INT0 sondern INTOOOOOOOOOO (großes O anstelle von NULL)

  GICR |= ( 1 << INT0 );

ABgesehen davon compiliert das dann auch

von Oliver (Gast)


Lesenswert?

Tja, dann wie immer:

Zip das Projektverzeichnis zusammen, und poste das hier mal.

Oliver

von Alex (Gast)


Lesenswert?

Tja verstehe wer will, ich habe gerade alles noch einmal neu aufgerissen 
und es funktioniert, mit der "0" hattest du recht (was peinlich genug 
ist)...
woran es am GICR lag verstehe ich nicht - denn von einer 
lese-/schreibschwäche wusste ich bisher nichts.
danke für die hilfe, jetzt wird weiterprobiert.
grüße
Alex

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.