?? smb_ex1.asm
字號:
orl A, #READ ; in READ_ADD
mov READ_ADD, A ;
setb SM_BUSY ; Occupy SMBus
setb STA ; Initiate Transfer
jb SM_BUSY, $ ; Wait for receive to finish
pop ACC ; Restore accumulator
ret
;---------------------------------------------------------------------------------------
; SMBus_Init
; SMbus initialization routine
;
; - Configures and enables the SMBus.
; - Sets SMBus clock rate.
; - Enables SMBus interrupt.
; - Clears SM_Busy flag for first transfer.
SMBus_Init:
mov SMB0CN, #04h ; Configure SMBus to send ACKs on acknowledge cycle
mov SMB0CR, #0B0h ; SMBus clock rate = 100KHz, per SMB0CR equation:
; SMB0CR = -(SYSCLK)/(2*Fscl)
orl SMB0CN, #40h ; Enable SMBus
orl EIE1, #02h ; Enable SMBus interrupts
clr SM_BUSY
ret
;--------------------------------------------------------------------------------------
; INTERRUPT VECTORS
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
; SMBus ISR
;
; Implemented as a state table lookup, with the SMBus status register as the index.
; SMBus status codes are multiples of 8; thus the status code can be used to index
; program segments that are spaced by 8 bytes. Each 'org' command indicates
; a new state, offset from the beginning of the table by its status code value.
;
; Note that only 8 bytes are available to process each state. In the cases where
; more than 8 bytes are necessary, the code jumps to a program location outside
; of the state table. This is only necessary in the state 'SMB_MTDBACK'.
SMBus_ISR:
push PSW ;
push ACC ;
push DPH ; Resource preservation
push DPL ;
push ACC ;
mov A, SMB0STA ; Load accumulator with current SMBus state.
; State corresponds to the address offset
; for each state execution
anl A, #7Fh ; Mask out upper bit, since any states that
; set this bit are not defined in this code.
mov DPTR, #SMB_STATE_TABLE ; Point DPTR to the beginning of the state table
jmp @A+DPTR ; Jump to the current state
; SMBus State Table------------------------------------------------------------------------
SMB_STATE_TABLE:
; SMB_BUS_ERROR
; All Modes: Bus Error
; Reset hardware by setting STOP bit
org SMB_STATE_TABLE + SMB_BUS_ERROR
setb STO
jmp SMB_ISR_END ; Jump to exit ISR
; SMB_START
; Master Transmitter/Receiver: START transmitted.
; The R/W bit will always be a zero (W) in this state because
; for both write and read, the memory address must first be written.
org SMB_STATE_TABLE + SMB_START
mov SMB0DAT, WRI_ADD ; Load slave address + W
clr STA ; Manually clear START bit
jmp SMB_ISR_END ; Jump to exit ISR
; SMB_RP_START
; Master Transmitter/Receiver: Repeated START transmitted.
; This state should only occur during a read, after the memory
; address has been sent and acknowledged.
org SMB_STATE_TABLE + SMB_RP_START
mov SMB0DAT, READ_ADD ; Load slave address + R
clr STA ; Manually clear START bit
jmp SMB_ISR_END
; SMB_MTADDACK
; Master Transmitter: Slave address + WRITE transmitted.
; ACK received
org SMB_STATE_TABLE + SMB_MTADDACK
mov SMB0DAT, MEM_ADD ; Load memory address
setb BYTE_SENT ; BYTE_SENT=1: In the next ISR call,
; the memory address will have just been
; sent.
jmp SMB_ISR_END
; SMB_MTADDNACK
; Master Transmitter: Slave address + WRITE transmitted.
; NACK received. The slave is not responding. Try again with
; acknowledge polling. Send STOP + START.
org SMB_STATE_TABLE + SMB_MTADDNACK
setb STO
setb STA
jmp SMB_ISR_END
; SMB_MTDBACK
; Master Transmitter: Data byte transmitted. ACK received.
; This state is used in both read and write operations.
; Check BYTE_SENT; if 1, memory address has just been sent. Else,
; data has been sent.
org SMB_STATE_TABLE + SMB_MTDBACK
jbc BYTE_SENT, ADDRESS_SENT ; If BYTE_SENT=1, clear bit and
; jump to ADDRESS_SENT to process
; outside of state table.
jmp DATA_SENT ; If BYTE_SENT=0, data has just been sent,
; transfer is finished.
; jump to end transfer
; SMB_MTDBNACK
; Master Transmitter: Data byte transmitted. NACK received.
; Slave not responding. Send STOP followed by START to try again.
org SMB_STATE_TABLE + SMB_MTDBNACK
setb STO
setb STA
jmp SMB_ISR_END
; SMB_MTARBLOST
; Master Transmitter: Arbitration Lost.
; Should not occur. If so, restart transfer.
org SMB_STATE_TABLE + SMB_MTARBLOST
setb STO
setb STA
jmp SMB_ISR_END
; SMB_MRADDACK
; Master Receiver: Slave address + READ transmitted. ACK received.
; Set to transmit NACK after next transfer since it will be the
; last (only) byte.
org SMB_STATE_TABLE + SMB_MRADDACK
clr AA ; NACK sent on acknowledge cycle
jmp SMB_ISR_END
; SMB_MRADDNACK
; Master Receiver: Slave address + READ transmitted. NACK received.
; Slave not responding. Send repeated START to try again.
org SMB_STATE_TABLE + SMB_MRADDNACK
clr STO
setb STA
jmp SMB_ISR_END
; SMB_MRDBACK
; Master Receiver: Data byte received. ACK transmitted.
; Should not occur because AA is cleared in previous state.
; Send STOP if state does occur.
org SMB_STATE_TABLE + SMB_MRDBACK
setb STO
jmp SMB_ISR_END
; SMB_MRDBNACK
; Master Receiver: Data byte received. NACK transmitted.
; Read operation completed. Read data register and send STOP
org SMB_STATE_TABLE + SMB_MRDBNACK
mov RECEIVE_BYTE, SMB0DAT
setb STO
setb AA ; Set AA for next transfer
clr SM_BUSY
jmp SMB_ISR_END
; End of State Table--------------------------------------------------------------
;---------------------------------------------------------------------------------
; Program segment to handle SMBus states that require more than 8 bytes of program
; space.
; Address byte has just been sent. Check RW. If R (1), jump to RW_READ.
; If W, load data to transmit into SMB0DAT.
ADDRESS_SENT:
jb RW, RW_READ
mov SMB0DAT, TRANSMIT_BYTE ; Load data
jmp SMB_ISR_END ; Jump to exit ISR
; Operation is a READ, and the address byte has just been sent. Send
; repeated START to initiate memory read.
RW_READ:
clr STO
setb STA ; Send repeated START
jmp SMB_ISR_END ; Jump to exit ISR
; Operation is a WRITE, and the data byte has just been sent. Transfer
; is finished. Send STOP, free the bus, and exit the ISR.
DATA_SENT:
setb STO ; Send STOP and exit ISR.
clr SM_BUSY ; Free SMBus
jmp SMB_ISR_END ; Jump to exit ISR
;---------------------------------------------------------------------------------
; SMBus ISR exit.
; Restore registers, clear SI bit, and return from interrupt.
SMB_ISR_END:
clr SI
pop ACC
pop DPL
pop DPH
pop ACC
pop PSW
reti
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -