Hallo,
ich lasse bei einem Atmega328 einen interrupt bei jedem Flankenwechsel
durchlaufen.
1
...
2
EICRA |= (1 << ISC00);
3
EIMSK |= (1 << INT0);
4
5
...
6
7
ISR(INT0_vect) //Button
8
{
9
}
Das funktioniert auch. Allerdings möchte ich bei steigender und bei
fallender Flanke etwas anderes ausführen.
Dazu möchte ich den Pegel des Pins abfragen, weiss aber nicht genau wie
(zumindest funktioniert es nicht) Auf der Tutorial-Seite war ich. Da
habe ich aber nur herausgefunden, wie man einen 'normalen' pin abfragt
1
if( PIND & (1<<PD2) )
Das ist zwar der Pin, wo auch der INT0 dranne ist, aber ist es auch
möglich, direkt den INT0 status (nicht über PD2) abzufragen? An anderen
Controllern liegt dieser ja nicht unbedingt an PD2.
Frank
> aber ist es auch möglich, direkt den INT0 status (nicht über PD2)> abzufragen?
Du kannst den Interrupt Status abfragen, aber Dir fehlt dann immer noch
Information, ob der Interrupt aufgrund einer steigenden oder fallenden
Flanke ausgelöst wurde. PD2 abzufragen ist dann schon korrekt.
Vermutlich hast du das Risiko bereits erkannt, das sich der Status der
Leitung PD2 zwischen dem Auslösen des Interrupts und dem Abfragen des
Pins ändern kann. Ist halt so, ich glaube dagegen gibt es keine
Patentlösung.
Es stellt sich die Frage nach den Rahmenbedingungen: wie hoch ist der
Systemtakt, sind andere Interrupts zugelassen bzw. gibt es
Interruptsperren, wie schnell kann sich das Eingangssignal ändern. Denn
im optimalen Fall erreicht man eine Latenz von etwa 10 Takten
entsprechend 500 ns.
Frank schrieb:> ... aber ist es auch> möglich, direkt den INT0 status (nicht über PD2) abzufragen?
Falls es um die Zuordnung anhand eines Identifizierers geht:
Nein. Das ist nicht (ohne weiteres) möglich, da INT0 allein den
Interrupt identifiziert und nicht den Anschluss, den Port oder das Bit
im dem Port, dessen Veränderung den Interrupt INT0 auslöst. Diese
Zuordnung ist aus dem Datenblatt ersichtlich.
In den XML-Files der jeweiligen Modelle (die mit AVRStudio V4
mitgeliefert wurden) ist diese Information allerdings enthalten. In den
Include-Files nicht. Das "ohne weiteres" oben bezog sich darauf. Man
müsste das XML-File auswerten.
Falls es um eine schnelle Erkennung der fraglichen Flanke geht:
Nein. Es gibt (ohne weiteres) nur die Möglichkeit den Zustand des
Eingangs ausdrücklich zu lesen.
Was das "ohne weiteres" betrifft, so kann man, wie der Benutzer
"Hardware" schon angedeutet hat, durch Aussenbeschaltung und Verwendung
von zwei Interrupts die Geschwindigkeit erhöhen. (Allerdings spart das
allenfalls so 3 bis 4 Takte, vielleicht 5).
Der "Zustand des Int0" ist bei Ausführung der zugeordneten ISR
"gefeuert". Man kan dann ablesen ob es ein steigende Order fallende
Flanke war, wenn man die zugehörende Konfigurationbits liest. Wenn sie
auf "jedem Pegelwechsel" stehen, dann weiß man nur, daß das Int0-Pin
gezappelt hat.
Oder man möchte wissen, ob der "Int0-Anschluß-Pin" High oder Löw ist.
Das wäre dann der "Zustand des PD2".
Theor schrieb:> Nein. Es gibt (ohne weiteres) nur die Möglichkeit den Zustand des> Eingangs ausdrücklich zu lesen.
Doch, die gibt es:
Man benutzt statt des INTx den entsprechenden Pinchange-Interrupt. Die
Flanke des am selben Pin liegenden INTx stellt man auf steigend oder
fallend.
Wenn der Pinchange ausgelöst wird, hat man schon mal einen
Flankenwechsel detektiert. Wenn man wissen möchte, welcher das war,
sieht man sich das Flag des INTx an. Ist der Trigger auf steigend
gestellt, ist das Flag bei steigender Flanke gesetzt, bei fallender
nicht.
Der INTx wird nicht aktiviert und braucht demzufolge auch keine ISR.
Wichtig ist, daß das Flag per Software gelöscht wird.
Die Idee ist wirklich verblüffend. Andererseits ist mir der Vorteil
gegenüber der herkömmlichen Methode noch nicht klar, schneller im Sinne
einer höheren Eingangsfrequenz wird man doch nicht, oder?
Man muss aber das INT0-Flag per Software zurücksetzen, was frühestens in
der PCINT-ISR passieren kann. Hilft also bei einem sehr kurzen Impuls
nicht weiter.
S. Landolt schrieb:> Man muss aber das INT0-Flag per Software zurücksetzen, was frühestens in> der PCINT-ISR passieren kann. Hilft also bei einem sehr kurzen Impuls> nicht weiter.
Das geht doch aber durch Lesen des Pinpegels auch nicht schneller, den
kannst du auch frühestens in der ISR auswerten - oder?
> durch Lesen des Pinpegels auch nicht schneller
Genau das meinte ich, das nämlich die beiden Methoden gleich schnell
sind, die 'neue', so sehr sie mich zuerst frappierte, nicht besser ist.
> Puls z.B. nur 2 Systemtaktperioden lang ist
Aber nach den 2 Takten haben wir eine fallende Flanke, was machen wir
mit der?
Oder habe ich es noch nicht begriffen?
Vermutlich nicht. Es geht doch erstmal um die korrekte Erkennung und
Unterscheidung einer Pulsflanke. Wielange die Verarbeitung dauern darf,
ist eine andere Sache.
Pardon, ich tu mich etwas schwer - wenn ich das INT0-Flag nicht schnell
genug zurücksetzen kann, dann kann ich doch auch keine Aussage über die
Flanke treffen, oder? Und wenn die Impulse so extrem kurz sind, sollte
nicht ein einfacher Interrupt ohne Flankenerkennung reichen?
Anscheinend hängst du bei einer speziellen Anwendung fest, bei der es
keinen Vorteil bringen würde.
Ein Gegenbeispiel:
Es soll mit einem sehr kurzen Puls ein längerer dauernder Vorgang
eingeleitet werden, der abhängig von der Pulsflanke ist. Während des
Vorgangs können keine weteren Pulse eintreten bzw. können ignoriert
werden.
Frank schrieb:> An anderen> Controllern liegt dieser ja nicht unbedingt an PD2.
Egal, ob INT0,1 oder PCINT, Du mußt immer den zugehörigen Pin abfragen,
d.h. Du mußt den AVR-Typ kennen.
Mit #ifdef __AVR_ATtiny13__ usw. kannst Du den Code für verschiedene
AVRs compilierbar machen.
(mal außer Acht gelassen, dass die Anforderung war, auf beide Flanken
unterschiedlich zu reagieren)
> Es soll mit einem sehr kurzen Puls ...
Konkret: ein sehr kurzer positiver Impuls mit niedriger
Wiederholfrequenz: wozu muss man da die Flanke erkennen?
Oder anders gefragt: die positive Flanke bekommt man in diesem Fall auch
mit einem einfachen Interrupt, und die negative? Würde die nicht bei der
'neuen' Methode unterschlagen, weil die ISR zu lange dauert?
Du versteifst dich auf sehr kurze Pulse. Nun, eine Mindestlänge von 3
Takten (Tiny25, PinChange) muss er eh dauern, sonst wird das PCIF nicht
gesetzt, auch bei dem 'einfachen' Interrupt.
Und wenn du, wie hier gefordert, auch auf die andere Flanke reagieren
willst und zudem noch die beiden unterscheiden musst, dann dauert es
eben noch länger.
Ohne Zeit zum Auswerten gibt es kein Ergebnis.
S. Landolt schrieb:> Oder anders gefragt: die positive Flanke bekommt man in diesem Fall auch> mit einem einfachen Interrupt, und die negative? Würde die nicht bei der> 'neuen' Methode unterschlagen, weil die ISR zu lange dauert?
Die Pegelabfrage und die Flagabfrage sind weitestgehend gleichwertig. In
erster Linie wollte ich nur zeigen, daß es auch noch eine andere Methode
als die Pegelabfrage gibt. Denn das wurde zuvor ausgeschlossen.
Thomas E. schrieb:> Doch, die gibt es:
Tolle Idee hier mit ISR und I-Flag Polling zu arbeiten. Dürfte mit dem
AVR die beste Lösung der Aufgabenstellung zu sein.
hardware schrieb:> Tolle Idee hier mit ISR und I-Flag Polling zu arbeiten.
Ist aber in der uC Welt üblich und nichts besonderes. Wenn beide Flanken
abgefragt werden sollen invertiert man das FlankenFlag oder nimmt einen
zweiten Eingang wenn die Pulslänge kürzer als die Latenz- und
Verarbeitungszeit ist.