Hallo alle zusammen,
ich stecke mit der ganzen AVR-Programmiererei in C immer noch in den
Anfängen fest. Leider gibt weder das Manual für den atTiny45 noch die
Suche im Internet eine klare Antwort:
Ich lasse bei Pin Change (PCINT0) einen Interrupt auslösen, und habe
einer entsprechende ISR. Konfiguriert habe ich:
--->Any logical change on INT0 generates an interrupt request.
Aber wie kann ich in der ISR nun herausbekommen, ob steigende oder
fallende Flanke anlag?
Bei dem folgenden Programmbeispiel würde die Abfrage natürlich keinen
Sinn ergeben, aber dieses kurze Beispiel ist mein Ausgangscode für
weitere Programme.
Gruss,
Stefan
Du musst dir den vorherigen Port-Zustand merken und mit dem aktuellen
vergleichen.
Um die Änderung zu finden, brauchst du nur die XOR-Funktion anwenden.
Ja, ich weiss, das ist zu kurz. Ich habe auch eine Version, wo ich eine
längere Zeit habe. Aber das ist ja auch nicht der springende Punkt. So
eine Abfrage habe ich schon versucht zu basteln, aber es funktionierte
nicht, weil ich:
1. nicht sicher bin, ob in dem Moment, wo ich in der ISR bin, der Pin
überhaupt noch auf dem gleichen Wert wie beim Auslösen des Interrupts
steht und
2. keine Ahnung habe, wie so eine Abfrage aussehen müsste.
Vielleicht hat ja eine eine Idee, wie man besipielsweise in das hier ein
entsprechende Abfrage einbauen könnte:
ISR (PCINT0_vect) // Interrupt on PCINT0 vector
{
wenn Flanke hoch ging,
dann Lampe (PORTB4) an,
ansonsten Lampe aus
}
Stefan R. schrieb:> 1. nicht sicher bin, ob in dem Moment, wo ich in der ISR bin, der Pin> überhaupt noch auf dem gleichen Wert wie beim Auslösen des Interrupts> steht und
Dann müsste das Signal schon relativ hochfrequent sein.
Stefan R. schrieb:> 2. keine Ahnung habe, wie so eine Abfrage aussehen müsste.>> Vielleicht hat ja eine eine Idee, wie man besipielsweise in das hier ein> entsprechende Abfrage einbauen könnte:>> ISR (PCINT0_vect) // Interrupt on PCINT0 vector> {> wenn Flanke hoch ging,> dann Lampe (PORTB4) an,> ansonsten Lampe aus>> }
am Anfang deines Programms (bzw. zu dem Zeitpunkt, an dem es für dich
interessant wird) speicherst du den Portzustand in einer Variablen.
Dann schaltest du die PCINT-Geschichte ein.
Wird der Interrupt nun ausgelöst, vergleichst du Bitweise die Variable
mit dem aktuellen Portzustand (den du dir auch in einer Variablen
zwischenspeichern kannst/solltest).
Eine steigende Flanke erkennst du daran, dass das Bit in der ersten
Variablen 0 ist und beim aktuellen Portzustand 1.
Am Ende der ISR überträgst du dann noch den Portzustand in die
Vergleichsvariable, da diese ab jetzt den letzten Portzustand
wiedergibt.
Am Ende der I
da fehlt noch was...
Sollte heissen:
Am Ende der ISR überträgst du noch den "aktuellen" Portzustand in die
Vergleichsvariable, da diese den vorhergehenden Portzustand wiedergibt.
OK, das habe ich verstanden. Aber: wie könnte so der Code aussehen, der
den Zusatnd des Ports abfragt?
Ich habe die ISR umgeschrieben. Immer wenn ein Flankenwechsel gemeldet
wird, soll nachgeschaut werden, ob die Flanke oben oder unten ist. Ob
ich einen vorigen Zustand vorliegen habe, ist da ja zunächst mal
unerheblich.
Wenn Level high ist, dann Lampe an, wenn Level nach Interrupt low ist,
dann Lampe aus.
Man muss es an der LED sehen können, denn wenn ich sie direkt an den
Eingang halte, wo PWM ankommt, leuchtet sie auch leicht.
Meine ISR funktioniert allerdings nicht:
Das ISC00 Bit hat nichts mit dem Pin Change Interrupt z tun, nur mit
Ext. Interrupt 0
Um den Zustand auf einem PIN abzufragen muß Du das PINB Register
abfragen
IF .. PINB ..
OK, das wäre ja dann mit einer Sicherung des Zustandes. Aber es muss
doch auch ohne gehen, indem ich einfach frage: in welchem Zustand ist
PORTB, Bit 1? Und zwar genau dann, wenn ein Interrupt ausgeführt wird.
etwas Blödsinn habe ich auch geschrieben: Die XOR-Operation zeigt jeden
Wechsel mit "1" an, nicht nur die steigenden Flanken.
Dafür kann man damit herausfinden, welcher Kanal eine Flanke hatte...
Stefan R. schrieb:> OK, das wäre ja dann mit einer Sicherung des Zustandes. Aber es muss> doch auch ohne gehen, indem ich einfach frage: in welchem Zustand ist> PORTB, Bit 1? Und zwar genau dann, wenn ein Interrupt ausgeführt wird.
Und wenn ein Port die ganze Zeit auf "1" gesetzt ist? Dann würdest du
nach deiner Definition das auch als Flanke werten.
Naja, dann würde ja aber auch kein Interrupt ausgelöst werden, wenn ich
das richtig verstehe. Also noch einmal Entschuldigung: ich habe wirklich
verdammt wenig Ahnung. So wenig, dass ich das PINB-Register nicht kannte
und jetzt erst einmal nachlesen muss ;-)
Stefan R. schrieb:> OK, das wäre ja dann mit einer Sicherung des Zustandes.
Das ist völliger Unsinn.
Der vorherige Zustand ist das Gegenteil vom jetzigen. Immer.
STK500-Besitzer schrieb:> Eine steigende Flanke erkennst du daran, dass das Bit in der ersten> Variablen 0 ist und beim aktuellen Portzustand 1.
Wenn der Zustand 1 ist, war er vorher 0. Sonst wäre der Interrupt nicht
ausgelöst worden.
Da muß man sich gar nichts merken.
Der Pin-Change-Interrupt wird ausgelöst, wenn sich der Zustand ändert.
Und zwar immer und nur dann. Da wird nichts eingetsellt.
Die Level-Einstellungen sind für INT0 und INT1.
mfg.
Stefan R. schrieb:> Naja, dann würde ja aber auch kein Interrupt ausgelöst werden, wenn ich> das richtig verstehe. Also noch einmal Entschuldigung: ich habe wirklich> verdammt wenig Ahnung. So wenig, dass ich das PINB-Register nicht kannte> und jetzt erst einmal nachlesen muss ;-)
Willst du nur einen Pin auswerten? PCINT ist für eine Gruppe von Pins
gedacht...
So, jetzt geht's offensichtlich so, wie ich es wollte, danke Deiner
Hilfe und dem Hinweis, darauf, dass es auf die Register PINx. ein wenig
peinlich ist mir das nun schon :-) Danke!
Stefan R. schrieb:> Naja, dann würde ja aber auch kein Interrupt ausgelöst werden, wenn ich> das richtig verstehe.
Wenn du nur für genau einen PIN den Interrupt aktivierst, ja. Aber der
PCINT kann ja auch von mehr als einem Pins ausgelöst werden. Und wenn du
das machst, mußt du nicht nur erkennen, welche Flanke, sondern auch
welcher Pin den Interrupt ausgelöst hat.
STK500-Besitzer schrieb:> Willst du nur einen Pin auswerten? PCINT ist für eine Gruppe von Pins> gedacht...
Warum denn nicht? PCINT ist nicht für eine Gruppe von Interrupts
gedacht, sondern verwendet eine ISR für bis zu 8 Pins.
Dabei ist der Nachteil gegenüber INT0/1, daß man noch nach der
Interruptquelle suchen muß. Je nach Maskierung gibt es dabei 1 - 8
Möglichkeiten.
mfg.
Praktisch gedacht:
Um eine Lampe oder LED einzuschalten (Trägheit des Betrachters), braucht
es wahrlich keinen Interrupt mit Flankenerkennung. Das ist alles ganz
locker mit Polling zu erschlagen.
Die ganzen Ratschläge sind eher akademischer Natur, praktischen Nutzen
haben sie nicht, eher im Gegenteil, sie komplizieren alles nur unnötig.
Thomas Eckmann schrieb:> STK500-Besitzer schrieb:>> Willst du nur einen Pin auswerten? PCINT ist für eine Gruppe von Pins>> gedacht...> Warum denn nicht? PCINT ist nicht für eine Gruppe von Interrupts> gedacht, sondern verwendet eine ISR für bis zu 8 Pins.> Dabei ist der Nachteil gegenüber INT0/1, daß man noch nach der> Interruptquelle suchen muß. Je nach Maskierung gibt es dabei 1 - 8> Möglichkeiten.>> mfg.
Das ist mir schon klar. Wenn man aber nur einen Pin auswerten will, kann
man sich das ganze Gehampel sparen, indem man einen dedizierten
Interrupt-Pin benutzt und da die gewünschte Flanke einstellt.
slow schrieb:> Das ist alles ganz locker mit Polling zu erschlagen.
Noch lockerer macht man das mit dem Pin-Change-Interrupt.
slow schrieb:> braucht es wahrlich keinen Interrupt mit Flankenerkennung.
Das ist in diesem Zusammhang in der Tat nur Gesülze.
mfg.
Thomas Eckmann schrieb:> STK500-Besitzer schrieb:>> Willst du nur einen Pin auswerten? PCINT ist für eine Gruppe von Pins>> gedacht...> Warum denn nicht? PCINT ist nicht für eine Gruppe von Interrupts> gedacht, sondern verwendet eine ISR für bis zu 8 Pins.
Es ist aber schlecht, mal so ganz pauschal zu behaupten, sich den
vorherigen Zustand zu merken, sei Unsinn. Normalerweise muß man das ja
sehr wohl tun. Es gibt aber einen Spezialfall, für den man es sich
sparen kann. Dir ist das klar, aber dem TE nicht. Und auch wenn er im
Moment vielleicht nur einen Pin braucht, fragt er spätestens dann wieder
hier nach, wenn der zweite Pin dazukommt und er sich daran erinnert, daß
es ja Unsinn ist, sich den alten Zustand zu merken. Deshalb ist es
besser, ihm das gleich richtig zu erklären.
Also, ich will nicht nur eine Lampe ein- oder ausschalten. Ich bekomme
von einem RC-Empfänger alle 20ms einen Impuls von 1-2ms Länge. Je
nachdem, wie lang der ist möchte ich mittels PWM an einem der Ausgänge
über einen MOSFET eine Glühkerze für einen Verbrenungsmotor dimmen.
Das ganze vorhin ist einer der Schritte auf dem Weg dorthin. Auf dem
Arduino läuft die ganze Anwendung schon, allerdings ist der für ein
Flugzeug zu schwer, zu gross und zu teuer.
Stefan R. schrieb:> Ich bekomme von einem RC-Empfänger alle 20ms einen Impuls von 1-2ms> Länge. Je nachdem, wie lang der ist
Dann vergiss' das mit dem Pin-Change und guck' dir mal bei den Timern
die Input Capture Unit an. Das ist genau dafür gemacht.
mfg.
Stefan R. schrieb:> Also, ich will nicht nur eine Lampe ein- oder ausschalten. Ich bekomme> von einem RC-Empfänger alle 20ms einen Impuls von 1-2ms Länge. Je> nachdem, wie lang der ist möchte ich mittels PWM an einem der Ausgänge> über einen MOSFET eine Glühkerze für einen Verbrenungsmotor dimmen.>> Das ganze vorhin ist einer der Schritte auf dem Weg dorthin. Auf dem> Arduino läuft die ganze Anwendung schon, allerdings ist der für ein> Flugzeug zu schwer, zu gross und zu teuer.
Wieso wusste ich nur, dass es sich mal wieder um die
Modellbau-Problematik handelt? ;)
In der Codesammlunbg hat jemand schon etwas derartiges gepostet. Auch
mit einer Servoansteuerung allerdings als Quasi-Polling, da er im
20µs-Intervall die Portpins abfragt und die Flanke selber feststellt.
Da hatte ich auch die "Idee" mit dem XOR her...
Wenn es nur um einen Pin geht, kann man für den Zweck noch viel besser
die Input-Capture-Einheit benutzen.
Die PCINT-Geschichte wollte ich schon lange mal in Angriff nehmen...
sollte langsam mal losgehen...
Stefan R. schrieb:> Anfängen fest. Leider gibt weder das Manual für den atTiny45 noch die> Suche im Internet eine klare Antwort:
Input Capture auf'm ATtiny45 ???
n
External schrieb:> Stefan R. schrieb:>>> Anfängen fest. Leider gibt weder das Manual für den atTiny45 noch die>> Suche im Internet eine klare Antwort:>> Input Capture auf'm ATtiny45 ???
Ja, nee, der nun nicht. Man kann sich den Controller aber auch nach den
durch die Anwendung vorgegeben Anforderungen aussuchen...
Das nächste bei dieser Aufgabe ist dann ja eh die Timer-Geschichte...