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.
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.
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!
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
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
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".
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.
Alex schrieb: > ayway - GICR (statt GIMSK) und INT0 sind immernoch undeklariert Hast du auch den Mega16 im AVRStudio eingestellt? Oliver
ja, die selben einstellungen wie immer (und da funzt alles) und zur sicherheit gerade noch einmal überprüft...
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, dann wie immer: Zip das Projektverzeichnis zusammen, und poste das hier mal. Oliver
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.