📄 iic_os2.asm
字号:
DO_30:
CJNE A,#status_OK_,DO_35
CLR IIC_failure
CLR i_am_a_slave
DO_X:
MOV A,IIC_status
MOV IIC_final_status,A
RET
;
;if 'iic_timer' overflows, have an IIC bus timeout error.
;
DO_ERR:
CALL MORE_00_SUB ;clear all registers
ANL IIC_status,#status_upper_mask_ ;preserve upper nibble
ORL IIC_status,#status_timeout_ ;indicate inactivity
CALL DO_ERRX
;
;do error recovery here - i.e. lost arbitration, bus error.
;Alternately, let the calling routine interrogate 'IIC_final_status'
;so that the main routines decide what to do for various errors. For
;development and debug purposes, this example routine ignores the
;errors.
;
DO_35:
SETB IIC_failure ;indicate a failed IIC session
SJMP DO_X
DO_ERRX: ;ensure the interrupt bit is cleared
RETI
;
;==========
;"IIC_time"
;Subroutine to increment IIC timeout timer. ACC returns 0 if timeout
;occurs. Should make this an actual timer in your system so that
;the amount of time for a timeout is deterministic. Note that the
;"IIC_VECTOR" routine resets this timer as well.
;
IIC_time:
INC iic_timer
MOV A,iic_timer
JNZ time_X
INC iic_timer + 1
MOV A,iic_timer + 1
time_X:
RET
;
;============================================================================
;Subroutine "FETCH_COMMAND"
;DESCRIPTION:
;============
;This subroutine fetches a byte from the address 'IIC_Command_File_adrs' in
;code memory space. If "FETCH_COMMAND_0" is called, then the address pointer
;'IIC_Command_File_adrs' is not incremented at exit, otherwise the address
;pointer is incremented.
;INPUT:
;======
;'IIC_Command_File_adrs' holds the address of the byte to be retreived.
;OUTPUT:
;=======
;ACCumulator holds the retreived byte.
;'IIC_Command_File_adrs' is incremented (not if "FETCH_COMMAND_0" is called).
;
FETCH_COMMAND_0:
CLR C ;carry indicates whether pointer inc or not
SJMP FC_10
FETCH_COMMAND:
SETB C
FC_10:
MOV DPL,IIC_Command_File_adrs ;no, must be XDATA or CODE
MOV DPH,IIC_Command_File_adrs+1
FC_Code:
CLR A
MOVC A,@A+DPTR
FC_exit:
JNC FCX_10 ;don't increment pointer if no carry
INC DPTR ;if carry set, increment pointer
FCX_10:
MOV IIC_Command_File_adrs,DPL ;restore pointer
MOV IIC_Command_File_adrs+1,DPH
RET
;
;============================================================================
;Subroutine "FETCH_DATA"
;DESCRIPTION:
;============
;This subroutine is used by all the IIC_OS2 states to get the next data byte
;from the address 'IO_address' in the memory space indicated in
;'Data?adrs?space'. This routine also saves the fetched data in the byte
;'last_data' so error recovery can be easiy done. Before this routine exits,
;the pointer 'IO_buffer_adrs' is incremented. For the 'immediate_' directive,
;simply get the next data byte from the command file stream.
;Fetched data returned in ACCumulator.
;INPUT:
;======
;'IO_address' has address where data is to be fetched from. If the target
; space is DATA, then the LSByte of 'IO_address' is the full
; address and the MSByte is ignored.
;'Data?adrs?space' holds the information for which address space is to be
; targetted for fetching the data.
;OUTPUT:
;=======
;ACCumulator is loaded with the fetched byte.
;'last_data' gets the fetched byte as well.
;'IO_address' is incremented (unless in immediate option in which case the
; 'IO_address' is meaningless).
;
FETCH_DATA:
JNB immediate_data,FD_10
CALL FETCH_COMMAND ;if immediate option, get data from
JMP FD_x2 ;command file stream
FD_10:
JB IO_Data,FD_Data ;is data in DATA space?
MOV DPL,IO_buffer_adrs ;no, then must be XDATA or CODE space
MOV DPH,IO_buffer_adrs+1
JB IO_Code,FD_Code ;is it in CODE space?
FD_Xdata:
MOVX A,@DPTR ;no, it must be in XDATA space
FD_exit:
INC DPTR ;bump pointer
MOV IO_buffer_adrs,DPL ;restore pointer
MOV IO_buffer_adrs + 1,DPH
FD_x2:
MOV last_data,A ;store data
RET
;
;enter here if data is in CODE space
;
FD_Code:
CLR A
MOVC A,@A+DPTR
SJMP FD_exit
;
;enter here if data is in DATA space
;
FD_Data:
MOV R0,IO_buffer_adrs
MOV A,@R0
MOV last_data,A
INC R0
MOV IO_buffer_adrs,R0
RET
;
;============================================================================
;Subroutine "STORE_DATA"
;DESCRIPTION:
;============
;This subroutine stores incoming data in the address 'IO_address' in the
;data space indicated in 'Data?adrs?space'. Only XDATA and DATA spaces
;are valid since we cannot write into the CODE space.
;INPUT:
;======
;ACCumulator has data to be stored. This data is not corrupted.
;'IO_address' holds address for where data is to be stored
;'Data?adrs?space' (bit addressable) describes which data space is to
; be targetted.
;OUTPUT:
;=======
;ACCumulator contents not corrupted by subroutine
;ACCumulator contents are stored in address as described above.
;'last_data' holds a copy of the data.
;'IO_address' is incremented.
;
STORE_DATA:
JB IO_Data,SD_Data ;is target area DATA?
SD_Xdata:
MOV DPL,IO_buffer_adrs ;no, then must be XDATA so load
MOV DPH,IO_buffer_adrs+1 ;address into DPTR
MOVX @DPTR,A ;store the data
MOV last_data,A ;and copy it
INC DPTR ;bump the address pointer
MOV IO_buffer_adrs,DPL ;and restore it
MOV IO_buffer_adrs+1,DPH
RET
;
;enter here if the target space is DATA
;
SD_Data:
MOV R0,IO_buffer_adrs ;get the address into R0
MOV @R0,A ;store the data
MOV last_data,A ;and copy it
INC R0 ;bump the address pointer
MOV IO_buffer_adrs,R0 ;and restore it
RET
$eject
;
;===========================================================================
;IIC interrupt vector
;Everytime a significant event occurs on the IIC bus (a start, stop, error,
;etc.), this interrupt routine is entered. This routine reads the IIC
;hardware SFR called 'S1STA' to determine what state the IIC hardware is in.
;Each state has it's own processing routine as shown below.
;The multi-master rotuines shown are very simple in this module - multi-
;master functions are very dependent on the system being serviced. This
;module simply relinquishes control of the bus if another master wins
;arbitration; it will receive or send bytes if it is addressed as a
;slave.
;============================================================================
;
IIC_VECTOR:
PUSH PSW ;save all registers used in interrupt vector
PUSH ACC
PUSH DPL
PUSH DPH
PUSH AR0
;
;'S1STA', the SFR indicating IIC hardware status for the '552 takes on a
;limited range of values, namely 00H to 0C8H in steps of 08H. The following
;manipulation changes the 'S1STA' value to a number from 0 to 50 (decimal) in
;steps of 2 so a jump can be done from an 'AJMP' table (AJMP instruction is
;2 bytes long). In other words, divide 'S1STA' by 4!
;
;The only special case for S1STA is the 'No relevant state' = state 0F8H. In
;this state, there is no relevant information and the IIC spec. says to
;ignore the state completely. So I did.
;
MOV A,S1STA ;get SFR which holds hardware status of bus
CJNE A,#0F8H,IICV_10 ;check for 'No relevant state'
SJMP IIC_EXIT
IICV_10:
RR A
RR A
MOV DPTR,#S1STA_00
JMP @A+DPTR
;
;all sections exit here.
;The timeout timer 'iic_timer' is restarted everytime around, it is assumed
;that if an interrupt occurs, that more than likely, everything is OK.
;
IIC_EXIT:
MOV iic_timer,#LOW(max_wait_) ;reload timeout timer
MOV iic_timer + 1,#HIGH(max_wait_)
POP AR0
POP DPH
POP DPL
POP ACC
POP PSW
RETI
;
;----------------------------------------------------------------------------
;Jump table for interrupt routine entry above.
;----------------------------------------------------------------------------
;
S1STA_00:
AJMP MORE_00 ;Bus Error mode
AJMP MORE_08 ;Master Receiver/Transmitter Mode
AJMP MORE_10 ;Master Receiver/Transmitter Mode
AJMP MORE_18 ;Master Transmitter Mode
AJMP MORE_20 ;Master Transmitter Mode
AJMP MORE_28 ;Master Transmitter Mode
AJMP MORE_30 ;Master Transmitter Mode
AJMP MORE_38 ;Master Receiver/Transmitter Mode
AJMP MORE_40 ;Master Receiver Mode
AJMP MORE_48 ;Master Receiver Mode
AJMP MORE_50 ;Master Receiver Mode
AJMP MORE_58 ;Master Receiver Mode
AJMP MORE_60 ;Slave Receiver Mode
AJMP MORE_68 ;Slave Receiver Mode
AJMP MORE_70 ;Slave Receiver Mode
AJMP MORE_78 ;Sla
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -