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
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.
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!
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?
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
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...
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...
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
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.
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
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