PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Look up table



cipoint
15.03.2007, 17:03
Hallo,

wie funktioniert eine LUT? Also sowohl praktisch (in Assembler) als auch theoretisch.

ps: Habe den 89S8252, ist alt, aber wird mir von meiner Schule vorgeschrieben.

SIGINT
15.03.2007, 17:20
Hallo cipoint,
es ist schon eine Weile her, daß ich mit den 8051ern rumgespielt habe.
Der 89S8252 ist eigentlich ein relativ neuer 8051 Typ... es gibt noch ältere Varianten. Aber zum Table:

Du musst einfach irgendwo im Programmspeicher dein LUT ablegen und kannst dann mit dem Befehl "movc A,@(A+DPTR)" das Datenwort in den Akku laden. Vorher musst du natürlich die Startadresse des LUT ins DPTR laden und den Offset in den Akku.


LUT:
.db irgendwas....


MOV A,LOW(LUT)
MOV DPL,A
MOV A,HIGH(LUT)
MOV DPH,A
MOV A,LUT_Offset
MOVC A,@(A+DPTR)


Ist nicht getestet... sollte aber so ähnlich funktionieren.

Gruß,
SIGINT

cipoint
15.03.2007, 20:46
;Zweiter Versuch mit dem Drehimpulsencoder

include REG8252.INC

;Zuweisungen
SIG_A EQU P3.3 ;0
SIG_B EQU P3.2 ;1
LAST_STATE EQU R6
TEMP EQU R2

;Resets
MOV P2, #0
MOV LAST_STATE, #0

;************************************************* **************************************************

;Die Hauptschleife
LOOP: ACALL CHECK_DIG_STATE
SJMP LOOP

;************************************************* **************************************************

CHECK_DIG_STATE: ACALL READOUT_DIG ;Zustand auslesen und
MOV A, LAST_STATE ;im Accu an der Stelle
MOV B, #04h ;X X X X - - X X platzieren
MUL AB

ACALL READOUT_DIG ;Zustand auslesen, an der
ORL A, LAST_STATE ;Stelle X X X X X X - - platzieren
ANL A, #0Fh

MOV P2, A

MOV DPTR, #TABLE
JMP @A+DPTR

;************************************************* **************************************************

;Liest den Drehimpulsgeber aus und speichert den Zustand im Register LAST_STATE

READOUT_DIG: JB SIG_A, A_TRUE
SJMP A_FALSE

A_TRUE: JB SIG_B, STATE_2
SJMP STATE_1

A_FALSE: JB SIG_B, STATE_3
SJMP STATE_0

STATE_0: MOV LAST_STATE, #0 ;SIG_A=0 and SIG_B=0
RET

STATE_1: MOV LAST_STATE, #1 ;SIG_A=1 and SIG_B=0
RET

STATE_2: MOV LAST_STATE, #2 ;SIG_A=1 and SIG_B=1
RET

STATE_3: MOV LAST_STATE, #3 ;SIG_A=0 and SIG_B=1
RET

;************************************************* **************************************************

TABLE: SJMP NOA
SJMP CW
SJMP ERR
SJMP CCW
SJMP CCW
SJMP NOA
SJMP CW
SJMP ERR
SJMP ERR
SJMP CCW
SJMP NOA
SJMP CW
SJMP CW
SJMP ERR
SJMP CCW
SJMP NOA

;************************************************* **************************************************

NOA: NOP
RET

ERR: NOP
RET

CW: SETB P2.7
RET

CCW: CLR P2.7
RET

END

Der uC hängt sich auf, wenn SIG_A=0 und SIG_B=1 ist. Sobald der Debugger an die Zeile JMP @A+DPTR kommt, gibt er "Out of Code" aus. Ich kann mir das aber nicht erklären. Der ACCU enthält zu diesem Zeitpunkt 00001010 und springt sogar zu der Adresse in der Tabelle unten. Dann führt der NOP aus und gibt eben den Fehler aus.

Vielleicht überschreibe ich versehentliche wichtige Register?

SIGINT
16.03.2007, 14:45
Ich hab wie gesagt lange nichts mehr mit dem 8051 gemacht... wie war das mit dem Stackpointer? Musst du eventuell noch den Stackpointer initialisieren?

SprinterSB
16.03.2007, 16:04
Der SJMP ist 2 Bytes lang. Musst du nicht vor dem relativen Sprung noch den Akku mir der Länge des SJMP-Befehls multiplizieren?

Allserdings erklärt das nicht den Debugger-Fehler bei dir, weil 1010 (DEC=10, also state no. 5) ein gültiger Offset ist :-k