Hilfe mit Interrupts

Gast #1746568
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
#1746598
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.
Gast #1746638
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!
Gast #1747635
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...
Gast #1747643
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...
Gast #1747671
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.
Gast #1747713
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren