Hallo,
ich verwende einen MCP 23S08 als IO Extender. Alle Pins sind als Input
mit Pull-Up konfiguriert. Lesen und Scheiben klappt auch soweit prima.
Folgendes Problem: Ich möchte gern periodisch die Pins erfragen, die
seit dem letzten Abfragen eine Änderung erfahren haben. Das Data Sheet
klingt so als sollte das mit eingeschalteten Interrupts gehen (S. 18):
> INTF will always reflect the pin(s) that have an interrupt> condition. For example, one pin causes an interrupt to> occur and is captured in INTCAP and INF. If before clearing> the interrupt another pin changes, which would normally> cause an interrupt, it will be reflected in INTF, but not> INTCAP.
Ich sehe aber in dem Register immer nur den ersten Pin, der sich
geändert hat. Alle weiteren Änderungen gehen verloren, es sei denn, sie
passieren exakt gleichzeitig.
Geht das, was ich da vorhabe, oder muss ich tatsächlich die Interrupts
behandeln, wenn sie ausgelöst werden (was ich aktuell nicht tue)?
Danke & Grüße
Jörg
Das ist wirklich ein Problem.
Du wirst mit dem INTCAP-Register keine Freude haben.
Du mußt, wenn ein INT gemeldet wird, einfach das PORT-Register auslesen
und per XOR mit einer Schattenkopie im uC vergleichen, welche Bits
geändert wurden, und die dann abarbeiten.
Tipp:
Du solltest das PORT-Register nicht erneut abfragen, um eine
Schattenkopie zu erzeugen, weil dann schon wieder eine Änderung passiert
sein kann, sondern durch geschickte Nutzung des XOR-Befehls kannst Du
eine neue Schattenkopie errechnen, die du dann zum Vergleich speicherst.
Evtl. dann noch von INT-Abfrage auf zyklisches Polling wechseln.
Ich glaube auch nicht, daß eine sofortige INT-Behandlung alle Änderungen
erfassen würde...
Hallo Bernd,
erstmal vielen Dank für die Antwort! So richtig verstehe ich es aber
nicht.
Wie es aussieht, bin ich gezwungen, den Interrupt direkt zu behandeln
(was ich eigentlich aus verschiedenen Gründen vermeiden wollte).
Anderenfalls sehe ich zusätzliche geänderte Bits nicht. Der Text im
Datenblatt scheint mir schlicht falsch zu sein. Im Datenblatt des
nächstgrößeren Bausteins 23S17 taucht er übrigens nicht auf.
Polling würde halbwegs funktionieren, wenn ich es mit sehr hoher
Frequenz durchführe, aber das kann ich nicht garantieren. Macht auch
wenig Sinn, da es den µC unnötig beschäftigt hält und dann keine
Rechenleistung für andere Sachen mehr verbleibt.
In meinem Anwendungsfall hängen an den Eingängen des Extenders übrigens
mechanische Schalter, d.h. das Timing ist nicht ganz so kritisch. Ich
interessiere mich nur dafür, welche der Leitungen seit der letzten
Abfrage (die x Sekunden her sein kann) mindestens einmal auf Masse
gezogen wurden. Ich hatte nach dem Lesen des Datenblatts gehofft, dass
mir der Extender diese Pufferung liefert. Schade eigentlich.
Viele Grüße & einen guten Rutsch!
Jörg
Joerg Pleumann schrieb:> In meinem Anwendungsfall hängen an den Eingängen des Extenders übrigens> mechanische Schalter
Also schnarchlangsame Signale, da ist Pollen im Timerinterrupt die
übliche Methode.
Und das Entprellen macht der Timerinterrupt bequemer Weise gleich mit.
Ich würde 10ms Timerinterrupt einstellen, da langweilt sich der MC immer
noch sehr.
Peter
Hallo Peter,
Peter Dannegger schrieb:> Joerg Pleumann schrieb:>> In meinem Anwendungsfall hängen an den Eingängen des Extenders übrigens>> mechanische Schalter>> Also schnarchlangsame Signale, da ist Pollen im Timerinterrupt die> übliche Methode.> Und das Entprellen macht der Timerinterrupt bequemer Weise gleich mit.> Ich würde 10ms Timerinterrupt einstellen, da langweilt sich der MC immer> noch sehr.
Leider hat der µC noch ein paar andere (wichtigere) Sachen zu tun, so
dass ich ihn nicht auf diese Weise beschäftigen wollte. Ich habe aber
jetzt eine andere Lösung gefunden. Mein eigentliches Problem war, dass
ich nur noch eine Interrupt-fähige Leitung frei habe, aber potentiell
mehrere I/O-Extender anschließen wollte - ohne extra Logikbausteine
dazwischenhängen zu müssen. Ich bin eben eher zufällig im Datenblatt
darauf gestoßen, dass ich die Interrupt-Leitungen auf Open Drain stellen
und dann einfach zusammenhängen kann. Hab's mit zwei Extendern probiert.
Klappt prima. Problem gelöst. Wieder was gelernt.
Danke für Eure Antworten, guten Rutsch!
Grüße,
Jörg
Joerg Pleumann schrieb:> Leider hat der µC noch ein paar andere (wichtigere) Sachen zu tun, so> dass ich ihn nicht auf diese Weise beschäftigen wollte.
Nein!
Du beschäftigst ihn damit nicht, sondern langweilst ihn.
Mal angenommen, Deine super-duper wichtigen Sachen lasten die CPU zu 90%
aus.
Nun kommt noch ein Timerinterrupt mit 0,1% hinzu, macht zusammen 90,1%.
Ob nun 90% oder 90,1% CPU-Last, das macht keinen Unterschied.
Peter
Peter Dannegger schrieb:> Joerg Pleumann schrieb:>> Leider hat der µC noch ein paar andere (wichtigere) Sachen zu tun, so>> dass ich ihn nicht auf diese Weise beschäftigen wollte.>> Nein!> Du beschäftigst ihn damit nicht, sondern langweilst ihn.>> Mal angenommen, Deine super-duper wichtigen Sachen lasten die CPU zu 90%> aus.> Nun kommt noch ein Timerinterrupt mit 0,1% hinzu, macht zusammen 90,1%.> Ob nun 90% oder 90,1% CPU-Last, das macht keinen Unterschied.
Wahrscheinlich hast Du recht. Aber die Lösung mit Interrupt-on-Change
ist aus meiner Sicht trotzdem eleganter, weil sie die Anzahl der
Interrupts auf das Notwendige reduziert.
Frohes Neues!
Jörg
Joerg Pleumann schrieb:> Aber die Lösung mit Interrupt-on-Change> ist aus meiner Sicht trotzdem eleganter, weil sie die Anzahl der> Interrupts auf das Notwendige reduziert.
Aber nur, wenn die mechanischen Schalter per HW entprellt sind. Sonst
weißt Du nicht, wieviele Interrupts tatsächlich entstehen.
Gruß Dietrich
Hallo,
ich arbeite hier mit dem 23S17 und habe nach dem Studium dieser ganzen
IOC-Geschichte meine Software etwas umgestellt.
Ein Tastendruck erzeugt einen Interrupt (der in Int-Routine entprellt
wird) an dem Extender, den die CPU in der Hauptroutine abfragt und die
Tasten pollt. Dann wird quasi jedes Bit (8 Tasten) einzeln auf Änderung
getestet...