www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Hilfe mit Interrupts


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
  ISR(INT0_vect)
  {
    /* Interrupt Code */
  }

  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.
#include <avr/io.h>
#include <avr/interrupt.h>
 
ISR(INT0_vect)       /* veraltet: SIGNAL(SIG_INTERRUPT0) */
{
    /* Interrupt Code */
}

int main()
{
  // der pin PD2 steht schon auf Eingang, da ist
  // also keine weitere Aktion notwendig

  // je nachdem welche Hardware da drann hängt, müsste man
  // ev. einen Pullup aktivieren

  //
  // den INT0 spezifisch freischalten
  //
  GIMSK |= ( 1 << INTO );

  //
  // und Interrupts generell freigeben
  //
  sei();

  //
  // ab jetzt ist alles scharf. Wenn am Eingang INT0 etwas passiert
  // wird die ISR INT0_vect aufgerufen.
  //

  while( 1 )
    ;
}

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

Da musst du durch.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Christopher G. (cbg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datasheet vom µC und avr-libc Manual lesen (zumindest die benötigten 
Teile).
http://www.nongnu.org/avr-libc/user-manual/group__...

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast vergessen "avr/io.h" zu includieren

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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/...).
Das Register heißt beim Mega16 "GICR".

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver (Gast)
Datum:

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

Hast du auch den Mega16 im AVRStudio eingestellt?

Oliver

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
controller ist in den prjekt-optionen nicht eingestellt.

Autor: Alex (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, dann wie immer:

Zip das Projektverzeichnis zusammen, und poste das hier mal.

Oliver

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.