| ??? 06/13/03 01:08 Read: times |
#48266 - RE: Some questions Responding to: ???'s previous message |
Dennis:
Thanks for helping to explain. Waqar: The formula you were having questions about is used to compute the number of entries in the table. Later in the state dispatch code a check is made to make sure that the index to be used with the state address table is not too big for the size of the table. This is just a piece of "defensive" programming to prevent too big of index. If you call the routine CALL_TABLE with an index that is too big it will try to use code bytes beyond the end of the table as branch addresses. Needless to say if this happens the program would crash in a spectacular way. The routine CALL_TABLE as Dennis explained uses a common 8051 technigue to change the program address that is transferred into the program counter. It is indeed a little tricky the first time you see it, but it is an efficient way to handle branching through a table of pointers. I am not sure the original designers of the 8051 instruction set at Intel expecteced that programmers would pull a stunt like this trick but it does work. There is another way to make a branch table in 8051 code which I will show below. This technigue however makes bigger tables and is not really that much faster than the scheme I put in the original code sample.....but here is a snippett of the original code with the alternate table branch method coded into it.
;;*** alternate branch table method. Lines with *** at the
;;end are the lines changed from the original example
; here is the main loop state table for the processing
; of the states for a specific switch.
;
; States are defined as:
; State 0: Waiting for a switch input to show it was
; detected going low.
; State 1: Waiting for second verification of a switch
; input in the low state as a debounce verification.
; State 2: Waiting for 5 second counter time to expire while LED
; is kept on for 5 seconds
; State 3: Waiting for switch input to show high again
;
STATE_TABLE:
LJMP MAIN_STATE_0 ; branch to State 0 routine ***
LJMP MAIN_STATE_1 ; branch to State 1 routine ***
LJMP MAIN_STATE_2 ; branch to State 2 routine ***
LJMP MAIN_STATE_3 ; branch to State 3 routine ***
STATE_CNT EQU ($ - STATE_TABLE)/3 ;number of states ***
;
;
;***************************************************
; main loop process
;
; This processes the current state each switch in a round robin manner.
; Each state is dispatched whenever the timer 1 interrupt indicates that
; 1.25 milliseconds has gone by. Then the state routine for one switch is called
; followed by an increment of the switch number variable. The main loop
; then goes back to the top to wait for another 1.25 msec period to expire.
; Since we process each of 8 switches in turn the effective processing rate
; for each switch input is 1,25 msec * 8 = 10 mSec (or 100 Hz).
;---------------------------------------------------
;
MAIN_LOOP:
JNB Tick, MAIN_LOOP ; wait till a tick has gone by
;
CLR Tick ; clear bit once seen
;
MOV A, SwitchNo ; fetch the state for the current
ADD A, #SwitchStates ; switch
MOV R0, A
MOV A, @R0
CJNE A, #STATE_CNT,ML_A ; check for legal state number
ML_A:
JC ML_B ; state number OK
CLR A ; reset to 0 if invalid
MOV @R0, A
ML_B:
MOV DPTR, #STATE_TABLE ; point to state branch table
CALL CALL_TABLE ; call to state routine
;
MOV A, SwitchNo ; increment to next switch number
INC A
ANL A, #7 ; limit to 3 bits of switch number
MOV SwitchNo, A
;
JMP MAIN_LOOP ; go wait for next tick time
;***************************************************
;NAME: CALL_TABLE
; Routine to call a routine through a table.
; Come here with A as the 0-n index into the
; table and DPTR pointing to the base of the
; table. The return at end of called routine
; takes execution back to where this routine
; was called from. ***
;---------------------------------------------------
CALL_TABLE:
PUSH B ***
MOV B, #3 ; multiply index by 3 for LJMP access ***
MUL AB ***
POP B ***
JMP @A+DPTR ; branch to the entry of the table ***
END
Michael Karas |



