Guten Tag,
ich habe mir einen arduino due angeschafft und möchte mihc nun mit dem
thema interrupts vertraut machen.
Ich habe gelesen das der Due alle Pins für externe Interrupts nutzen
kann.
Ein einzelner Interrupt ist nicht so das problem. Angenommen ich möchte
an mehreren Pins Interrupts generieren, wie läuft das dann mit
prioritäten und wie legt man diese fest?
Hallo Jannus,
schau in das Datenblatt deinen Atmel AVR µC, den wir nicht kennen, dort
sind alle Interrupts beschrieben.
Und es gibt i.a. INT0-INTn die habe ihre eigenen Interrupt Einsprünge
und dann i.a. auch noch die PCINTn Interrupts.
Der PCINTn ist eine Zusammenfassung eines Port auf einem Interrupt
Einsprung.
Hier muss Dein Programm dann herausfinden, welcher der 8 Eingänge eine
Ports es gerade war und auch noch zu Checken welcher Spannungslevel
dieser Eingang gerade hatte, denn PCINTn Interrupts "zünden" immer auf
einen Signalwechsel als L->H UND H->L.
Den Rest Erklärungen überlasse ich dem Datenblatt.
Karl M. schrieb:> deinen Atmel AVR µC
Der Arduino Due ist ein SAM3X8E, ein Cortex-M3
Jannus schrieb:> Ein einzelner Interrupt ist nicht so das problem. Angenommen ich möchte> an mehreren Pins Interrupts generieren, wie läuft das dann mit> prioritäten und wie legt man diese fest?
Je niedriger die Zahl, desto hoeher die Prioritaet.
Eine Prioritaet setzt du mit:
1
NVIC_SetPriority(TC0_IRQn, 5); // setzen der prioritaet
Der TC0 IRQ erhaelt hier die Prioritaet 5, der Interrupt fuer den
Zufallszahlengenerator die Prio 10. Das heisst: TC0 unterbricht TRNG.
Die Prioritaeten gehen (glaube ich) von 1 bis 15.
1 -> ganz wichtig, 15 -> ueberhaupt gar nicht wichtig
Nimmst du die Arduinoe IDE oder Atmel Studio?
Jeder Port kann genau einen Interrupt auslösen, egal wie viele Pins du
dort mit Interrupt konfiguriert hast. Wenn ein GPIO also einen Interrupt
auslöst, musst du das ISR lesen, dort sind dann alle Bits gesetzt, die
einen Interrupt ausgelöst haben (könnten).
Daraus folgt, dass ein Port nur eine einzige Interruptpriorität für alle
Pins an diesem Port hat. Du kannst aber pro Port eine Priorität im NVIC
vorgeben.
Die Hardware kann durchaus einen Interrupt für jeden Pin auslösen. Es
wird aber für alle Pins an Port A der PIOA-Interrupt aufgerufen, für
alle Pins an Port B der PIOB-Interrupt und so weiter.
Wie die Arduino-Bibliotheken damit umgehen, weiß ich nicht (und
interessiert mich auch eher nicht). Es kann gut sein, dass das, was ich
beschrieben hatte, dadrin schon erledigt wird und die Interrupts dann
auf verschiedene "Interrupt-Handler" verteilt wird, je nachdem, an
welchem Pin sie aufgetreten sind.
Jannus schrieb:> m.n. schrieb:>> Was ist Dein 'Zweck'?>> steht doch oben alles
Interrupts als Selbstzweck? Das kann ich nicht nachvollziehen.
Wie das Atmel-Studio das Debugging unterstützt, weiß ich nicht. Wenn man
genau sehen will, wie der µC intern tickt, sind Demo-IDEs von Keil oder
IAR sehr sinnvoll: im laufenden Betrieb kann man sich Variablen und
Flags ansehen und ändern. Das nennt sich 'live watch' (bei IAR).
Jannus schrieb:> Es ist aber doch genau so möglich, das jeder Pin einen Interrupt> auslöst.
Ja, jeder Pin kann einen Interrupt auslösen, aber für einen Port gibt es
nur einen Interrupt-Handler, soll heißen: Alle Pins an Port A lösen den
Port A Interrupt aus, und du musst im Interrupt-Handler abfragen,
welcher Pin den Interrupt ausgelöst hat.
1
Interrupt_Handler_PortA() // weiss gerade nicht wie der genau heisst
Das selbe gilt z.B. auch für den UART/USART. Beim AVR gibt es zwei
interrupts, einen für senden, einen für empfangen. Beim Due gibt es nur
einen Interrupt, und du musst feststellen, welcher interrupt es war.
Kaj schrieb:> Ja, jeder Pin kann einen Interrupt auslösen, aber für einen Port gibt es> nur einen Interrupt-Handler, soll heißen: Alle Pins an Port A lösen den> Port A Interrupt aus, und du musst im Interrupt-Handler abfragen,> welcher Pin den Interrupt ausgelöst hat.
Angennommen ich schreibe folgende Programmzeile:
attachInterrupt(pin, state, CHANGE);
Wenn ich hierzu jetzt die ISR aufrufe weiß ich doch auch das an genau
diesem Pin ein Interrupt ausgelöst wurde. Oder ist es so, das ich pro
Port immer die gleiche ISR aufrufe?
Sprich das es so umgesetzt werden muss.
attachInterrupt(pin1, state, CHANGE); //Pin 1 an PortA
attachInterrupt(pin2, state, CHANGE); //Pin 2 an PortA
Oder geht es auch so:
attachInterrupt(pin1, state1, CHANGE); //Pin 1 an PortA
attachInterrupt(pin2, state2, CHANGE); //Pin 2 an PortA
Jannus schrieb:> attachInterrupt(pin, state, CHANGE);>> Wenn ich hierzu jetzt die ISR aufrufe weiß ich doch auch das an genau> diesem Pin ein Interrupt ausgelöst wurde. Oder ist es so, das ich pro> Port immer die gleiche ISR aufrufe?
Eines der schönen Dinge bei Computern ist es, dass es dem Computer
völlig egal ist, wenn du ein wenig herumprobierst.
Warum probierst du es nicht einfach aus?
Installier den Interrupt, häng einen Taster an den Pin (und einen
zweiten Taster an einen anderen Pin vom selben Port), mach noch eine LED
an einen anderen Port, lass das Programm laufen und drück auf den Taster
der eigentlich keinen Interrupt auslösen sollte.
Dann weisst du es genau.
Und das schönste: du hast es selbst herausgefunden.
Ein bisschen mehr Eigeninitiative!
Du wirst noch auf 1000-ende Dinge stossen, die auf den ersten Blick ein
paar Fragen aufwerfen. Willst du jedesmal wen fragen oder willst du
lernen, wie man sich selbst Antworten erschliesst und wie man
Testszenarien so entwirft, dass sie einem Antworten liefern?
Der Lerneffekt ist ungleich intensiver, wenn man selbst auf Dinge drauf
kommt. Dann passiert es dir auch nicht, dass du nach Dingen fragst, die
jetzt schon x mal beantwortet wurden.
Jannus schrieb:> Angennommen ich schreibe folgende Programmzeile:>> attachInterrupt(pin, state, CHANGE);
Eigenlich solltest du den Pin über die Funktion digitalPinToInterrupt()
dem Interrupt zuordnen bzw. beim Due nur 0 übergeben.