Hallo zusammen,
ich versuch grad mit einem Inkrementalgeber einen Zähler zu verändern
und den aktuellen Wert des Zählers zur Kontrolle über LEDs wieder
auszugeben. Als Controller verwende ich den AT89S8253.
Ein Signal des Gebers geht auf Port 3.2 und das andere auf Port 3.3. Der
Interrupt wird über Port 3.2 ausgelöst. Die LEDs sind an Port 0
angeschlossen.
Der Geber hat 15 Inkremente und 30 Raststellungen pro Umdrehung. Je
nachdem in welcher Stelle er sich gerade befindet zeigten die LEDs
entweder irgend ein Leuchtmuster an oder die LEDs 0 bis 6 leuchten und
die 7. blinkt. Ich hab im Moment keine Ahnung was ich an dem Programm
verändern muss und auch m Netz hab ich nichts gefunden.
1
#include <REG8253.H>
2
3
;------------------------------------------------
4
5
; Reservierung des Stack-Bereichs
6
7
?STACK SEGMENT IDATA
8
9
RSEG ?STACK
10
11
DS 10H
12
13
;------------------------------------------------
14
15
; Variablen im int. direkt adressierbaren RAM
16
17
Variablen SEGMENT DATA ;Variablen im direkt adressierbaren internen RAM
Ok, das hilft schonmal weiter. Die Auswertung nach einer festen Zeit mit
einem Timer Interrupt werd ich gleich mal ausprobieren. Aber ich hab
auch nochmal ins Datenblatt meines Gebers geschaut und leider hab ich
einen, bei dem der Rastpunkt genau auf der Flanke von Signal B liegt.
Und der AT89S8253 Mikrocontroller besitzt (so wie ich es bisher aus dem
Datenblatt verstanden hab) nur externe Interrupts für positive Flanken.
Daher muss ich das Signal wohl noch hardwaremäßig invertieren um ein
Interrupt mit der negativen Flanke auslösen zu können.
> so wie ich es bisher aus dem Datenblatt verstanden hab) nur externe> Interrupts für positive Flanken.
Soweit ich weiss besitzt er eher welche für negative Flanken... kann
mich aber auch täuschen...
Ralf
@ Peter:
Ich hab versucht deinen Code zu verstehen und auf meinem Controller zum
laufen zu bringen, aber beides ist mir leider nicht gelungen. Was die
Funktion "poll_encoder" in etwa macht konnte ich noch einigermaßen
nachvollziehen, aber bei der Funktion "read_encoder2" und bei der
Ausgabe auf den LEDs klappt das nicht. Im Anhang ist der Code so wie ich
ihn kompiliert hab.
@ Ralf:
Das wäre auch möglich. Aber zumindest dürfte es nicht beides geben. Von
daher bleibt das Problem das gleiche.
Michael L. schrieb:> Ausgabe auf den LEDs klappt das nicht.
Du solltest versuchen, sinnvolle Fehlerbeschreibungen zu machen.
klappt nicht ist voll für die Tonne, damit kann keiner was anfangen.
read_encoder2 gibt nur bei jedem 2.Puls was aus, damit pro Rastung nur
einmal gezählt wird.
Du kannst zu Testzwecken aber auch direkt enc_delta auf die LEDs
ausgeben.
Peter
Naja, "klappt nicht" war auch keine Fehlerbeschreibung, sondern nur die
Aussage, dass ich den Teil des Programms nicht versteh. Aber ich muss
zugegeben dass ich wirklich noch hätte schreiben sollen was auf dem
LED-Port passiert: Alle LEDs flackern und wenn ich am Geber drehe ändert
sich auch nichts.
Wenn ich enc_delta direkt auf die LEDs geb passiert das Gleiche.
Inzwischen hab ich aber ein eigenes Programm zum laufen gebracht. Das
läuft jetzt über ein Timer-Interrupt, welches alle 10ms auslöst. Dabei
werden auch nur die Flanken der Spur A und die Zustände der Spur B
ausgewertet. Das Programm ist vermutlich nicht so effizient wie deines,
aber zumindest hab ich jetzt ein Programm bei dem ich weiß was es macht.
Übrigens war der hauptsächliche Fehler dass das erste Programm nicht
funktioniert hat der, dass der externe Interrupt voreingestellt
zustands- und nicht flankengesteuert arbeitet. Das steht aber nicht im
Datenblatt, sondern in einem anderen Dokument das allgemein die
8051-Architektur beschreibt. Dort stand außerdem, dass es wirklich
fallende Flanken sind, die ein Interrupt auslösen.
Michael