Erstmal ein hallo an alle! :-) Ich besitze ein AT90USBKey und möchte folgendes Programm entwickeln: 2 Incrementalgeber ("Drehpotis" mit Gray-Code) sollen je eine Variable auf und runterzählen. Nebenbei muss der Prozessor verschiedene Tasks abarbeiten (SPI Schnittstelle, Temperatur auslesen usw.). Im Moment habe ich die Incrementalgeber ausgelesen und auf die LED's dargstellt. Ich habe das Signal mit einem Delay von 3ms (mit delay.h) entprellt. Dies funktioniert alles einwandfrei, jedoch möchte ich nun dass der Prozessor erst bei einer Veränderung des "Potis" dies abarbeitet und auch dass während der Entprellungszeit von 3ms andere "tasks" abgearbeitet werden können. Nun zu meiner Frage: Wie soll ich an das Programm rangehen, gibt es sowas wie eine Betriebssystemstruktur (bei C# könnte man ja thread.sleep machen und somit hätten andere Thread's vorrang). Wenn man es mit Timer lösen kann, hat mir einer ein Beispiel in C? Ich habe mal das C. File angehängt, falls ich mein aktuelles Programm ein bisschen ungenau beschrieben habe ;-) Besten Dank für eure wertvollen Tipps!
@ Fabian Metz (elmetzo) >2 Incrementalgeber ("Drehpotis" mit Gray-Code) sollen je eine Variable >auf und runterzählen. Nebenbei muss der Prozessor verschiedene Tasks >abarbeiten (SPI Schnittstelle, Temperatur auslesen usw.). Keine grosse Sache. >ich die Incrementalgeber ausgelesen und auf die LED's dargstellt. Ich >habe das Signal mit einem Delay von 3ms (mit delay.h) entprellt. Dies AUA!!! Delays sind böse. Nutze Timer. Hab leider kein Beispiel direkt für dich. Aber die Tutorials. Drehgeber AVR-Tutorial: Timer AVR-GCC-Tutorial >Nun zu meiner Frage: Wie soll ich an das Programm rangehen, gibt es >sowas wie eine Betriebssystemstruktur (bei C# könnte man ja thread.sleep Nein, eine einfach Endloschleife im Main, i der zyklisch dine Aufgabenbearbeitet werden. MFG Falk
Hi! Muss Falk zustimmen. Auf keinen Fall Threads oder Tasks in die Luft hängen. Gerade Hardware-nahe Schnittstellen, deren Zeitverhalten nicht vorhersehbar sind, sollte man nicht in die Abhängikeit eines Tasks stellen, sondern umgekehrt. Daher hast Du zwei Möglichkeiten: 1) Die Gray-Encoder hängen an IRQ-Fähigen Pinnen 2) Setzte einen Timer auf, der wegen der Entprellung auch ruhig im 10ms Bereich laufen kann, oder sogar noch etwas langsamer. Ich mache das grundsätzlich mit Timer, weil dadurch das Entprellen weg fällt, bzw sehr einfach wird: 1) Timer fragt Eingang ab und vergleicht mit vorhergehendem Wert 1a) Vorhergehender Wert ist gleich, nix passiert -> Exit 1b) Vorangegangener Wert ist unterschiedlich also neuen Stand speichern und ein Flag setzen, dass etwas passiert ist. In 1b) kannst Du schon das Gray-Decoding machen, und damit entweder ein Flag für Links oder Rechts setzen, oder aber einen Zähler verändern und das mit einem Flag dem Rest des Systems signalisieren. ( Ich glaube dieses Flag nennen C++/# Entwickler Semaphore, oder?) Gruß, Ulrich
Hi Ulrich
>1) Die Gray-Encoder hängen an IRQ-Fähigen Pinnen
Hmm, aber wenn ich die an einem IRQ-Pin habe dann würde ich ja gleich
mehrere Interrupts auslösen wenn die kontakte "prellen", oder eben halt
nach dem interrupt wieder warten...
Ich probiers mal mit dem Timer zu lösen, jedoch ist das ja nicht
ereignisgesteuert sondern einfach eine zyklische abfrage (polling). Aber
viel Zeit nimmt das ja nicht in anspruch...
Gruss Fabian
@ Fabian Metz (elmetzo) >Hi Ulrich >>1) Die Gray-Encoder hängen an IRQ-Fähigen Pinnen >Hmm, aber wenn ich die an einem IRQ-Pin habe dann würde ich ja gleich >mehrere Interrupts auslösen wenn die kontakte "prellen", oder eben halt >nach dem interrupt wieder warten... Eben, das macht man nicht so. Steht alles fein säuberlich im Artikel Drehgeber. MFG Falk
Ich habe ja auch nicht geschrieben, dass man das über IRQ machen soll, sondern es als nicht näher erklärte Option angeboten ( weil es eben Prell-Anfällig ist). Der Timer ist bei mechanischen Eingabegeräten immer vorzuziehen, weil er das Entprellen gleich mit erledigt. Durch Veränderung der Timer-Zeitbasis kann man dann sehr einfach den Punkt finden, an dem sich das System durch Prellen nicht zu sehr verwirren lässt, es aber auch ein schnelles Drehen nicht zum Stolpern bringt. Ich habe das zuletzt für eine Tastatur im PKW gemacht, wo neben dem Kontaktprellen noch andere Störeinflüsse hinzu kommen könnten. Dort habe ich eine zweite Stufe eingebaut in der Software. Bezogen auf den Gray-Encoder ( und mein Gott prellen die Dinger, wenn die älter werden!) sollte man das gleich vorsehen: 1. Interrupt-> Prüfe mit vorhergehendem Signalstand? Unterschied! Zwischen-speichern. 2. Interrupt-> Prüfe mit gemerktem Signalstand von 1.? Gleich-> Neuen Wert als Gray-Wert nehmen und mit vorhergehendem Gray-Wert die Drehrichtung ermitteln. Unterschied! -> Zwischen-speichern. Man überschreibt so lange den 1. Zwischenspeicher, bis man dort einen stabilen Zustand erreicht hat und vergleicht dann, ob sich dieser stabile Zustand vom letzten stabilen unterscheidet. Tut er das, dann wird der Zähler behandelt und / oder das/die Flag(s) gesetzt, um eine Drehung anzuzeigen. Um die Systemlast nicht zu sprengen und nicht auf jeden Drehimpuls direkt reagieren zu müssen ( was bei Systemen sinn macht, die gelegentlich schwer an einzelnen Tasks zu arbeiten haben), kann man auch einen Differenz-Zählerstand einbauen. D.h. der Timerinterrupt kumuliert die Drehereignisse in einem Zähler. Kommt die Software dann zur Auswertung, addiert sie diesen Zählerstand zu ihrem eigenen hinzu. Beispiel: Software ist mit Malen von Menügrafiken beschäftigt. Um das nicht zu sehr zu verlangsamen, oder den Menücode einfacher zu halten, nimmt sie dabei keine Eingaben entgegen. Ich kann jetzt trotzdem 5x nach recht drehen und 3x nach links. Wenn mein Menü gemalt ist, und der Balken stand auf Punkt 1, dann flitzt er jetzt auf Punkt 3. Natürlich sollte man diesen Differenzzähler als Signed ausführen :) So, sind nur ein paar Anregungen. Muss ja nicht alles auf einmal implementiert werden. Gruß, Ulrich
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.