i2c.asm
来自「DSP中用MCBSP模拟I2C接口的程序.其中DSP的型号是C5416」· 汇编 代码 · 共 679 行 · 第 1/2 页
ASM
679 行
;***SET UP AR4 POINTS TO BYTE TO BE SENT***
LD #_ODPTR,B ;Load addr of out-data to B
LD _ODBYTECTR, -8,A ;Move current byte pointer
STL A,POINTER ;Store it to POINTER (1ST= BYTE 0)
ADD A,B ;Update current btye pointer
STLM B,AR4 ;AR4 points to current byte
;***SET UP AR3 POINTS TO BIT TO BE SENT***
STM #MASK,AR3 ;AR3 points to MASK
RPT ODBITCTR ;Look up table (LUT)
LD *AR3+,A ;Store mask to A
AND *AR4, A ;Check if the bit is high or low
;***WRITE BIT***
CC releaseSDA,ANEQ ;Bit=1, SDA=high
CC pullSDA,AEQ ;Bit=0, SDA=low
;***TEST IF COME TO LAST BIT***
LD ODBITCTR,A ;If BITCTR=0(LSB) ie. end of byte
BC tint_ws_next_byte,AEQ ;goto next byte
SUB #1,A,B ;Decrement A and store to B
STL B,ODBITCTR ;Store back to register
B tint_ws_next ;Next bit
;***TEST IF COME TO LAST BYTE***
tint_ws_next_byte:
LD POINTER,B ;First byte is byte zero
ORM #K_ACK_1,_I2CSTATUS ;Enable ACK flag
ST #7,ODBITCTR ;Start from MSB (initiate next byte)
ADD #1,B ;Increment POINTER
STL B,POINTER ;Store back
ANDM #0FFH,_ODBYTECTR ;Prepare num of btye to send
LD _ODBYTECTR,A ;Load num of byte to A
SUB B,A ;A=(Num of byte) - (current byte POINTER)
BC tint_ws_end_write,AEQ ;If=0,no more to send,enable stop condition
LD POINTER,8,A ;Shift 8 places forward
LD _ODBYTECTR,B ;
OR B,A ;Combine POINTER and num of btye to send
STL A,_ODBYTECTR ;Update ODBYTECTR
B tint_ws_next ;Goto next byte
;***NO MORE DATA***
tint_ws_end_write: ;Do not update POINTER for last byte
ORM #K_STOP_1,_I2CSTATUS ;Enable STOP condition
ST #0,TEMP1_REG
;***PREPARE FOR NEXT BIT***
tint_ws_next:
ORM #K_CLKH_1,_I2CSTATUS ;Next TINT,enable releaseSCL
STM #STOP_TIMER,TCR ;stop timer
STM #K_SCL_LOW1,PRD ;load SCL low period(interrupt at 5us)
STM #START_TIMER,TCR ;start timer
B tint_end_isr ;
;***BUSY LINES OR UNKNOWN CONDITION
tint_busy: ;Unknown condition or lines are busy
;***REPORT ERROR TYPE***
ORM #K_ERR_1,_I2CSTATUS ;Turn error flag on
ST #K_ERR_UNKNOWN,ERRORCODE ;Give type of error
B tint_end_isr
;**************************************************************************
;**************************************************************************
;*****MAKE CLK->HIGH SEQUENCES*****
tint_clk_go_high:
CALL releaseSCL ;SCL=high
NOP ;Wait for a while. (Does SCL go high
NOP ;Wait for a while. immediately?)
NOP ;Wait for a while.
;***SYNCHRONIZATION***
;ST SPSA,AR2 ;AR2 points to SPSA(redundant,safety)
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA)=PCR
LD #K_DR_STAT_1,A ;Check if SCL go high?
AND *AR2-,A
BC tint_clk_go_high_yes, ANEQ ;if SCL=high, goto high_yes
;***SLAVE HOLD SCL LOW***
STM #STOP_TIMER,TCR ;stop timer
STM #K_PRD_VAL,PRD ;load PRD (interrupt at 1us)
STM #START_TIMER,TCR ;start timer
B tint_end_isr ;Do go_high procedure again
;***CLK GONE HIGH (SLAVE NO MORE HOLDING ONTO SCL)***
tint_clk_go_high_yes:
ANDM #K_CLKH_0,_I2CSTATUS ;Remove SCL go_high flag
;*****ACKNOWLEDGE SEQUENCE***
;***CHECK IF IT IS IN THE ACK PHASE (write slave)***
LD TEMP_REG,A ;Check if Slave release SDA line
BC tint_ack_test,AEQ ;Extra ACT flag=0 : ACK in progress
;*****END OF ACKNOWLEDGE SEQUENCE***
;*****READ THE CURRENT SDA LEVEL (FOR READ SLAVE MODE)***
;***CHECK IF MASTER-RECEIVER MODE (read slave)***
LD _I2CSTATUS,B ;
LD B,A ;Duplicate
AND #K_ADDR_1,A ;Check ADDR in i2c status
BC tint_clk_go_high_not_rs,ANEQ;If sending slave addr,goto not_rs
MVDK _I2CSTATUS,TEMP_REG ;Copy i2c status to temp register
ANDM #01100000B, TEMP_REG ;Mask on 6 and 5 bit (Mode of operation)
CMPM TEMP_REG,#K_READ_FROM_SLAVE ;Compare only 6 and 5 bit
BC tint_clk_go_high_not_rs,NTC ;If not 10,goto not_rs
;***CHECK IF IN ACK PHASE***
AND #K_ACK_1,B ;Check ACK in i2c status
BC tint_rs_mode,BEQ ;If ACK=0, goto rs_mode
;***CHECK IF GOING TO STOP SEQUENCE***
LD _I2CSTATUS,A ;Check if come to the last byte
AND #K_STOP_1,A ;Need to set extra TEMP_REG flag=0
BC tint_clk_go_high_not_rs,AEQ ;Bcos to avoid the unknown transition of SDA
ST #0,TEMP1_REG ;To prolong SDA=0 in stop sequences
;*****END OF READ THE CURRENT SDA LEVEL (FOR READ SLAVE MODE)***
tint_clk_go_high_not_rs:
;***END OF READ SLAVE MODE***
ORM #K_CLKL_1,_I2CSTATUS ;Enable SCL go_low flag
STM #STOP_TIMER,TCR ;stop timer
STM #K_SCL_HIGH,PRD ;load PRD (interrupt at 5us)
STM #START_TIMER,TCR ;start timer
B tint_end_isr ;Interrupt at 5us
;**************************************************************************
;**************************************************************************
;***MAKE CLK->LOW SEQUENCES***
tint_clk_go_low:
CALL pullSCL ;SCL=low
ANDM #K_CLKL_0,_I2CSTATUS ;Remove SCL go_low flag
STM #STOP_TIMER,TCR ;stop timer
STM #K_SCL_LOW2,PRD ;load SCL low period(interrupt at 5us)
STM #START_TIMER,TCR ;start timer
B tint_end_isr ;Interrupt at 5us
;**************************************************************************
;**************************************************************************
;***DISABLE FURTHER TIMER INTERRUPT***
tint_disable_tint:
ANDM #0FFF7H,IMR ;Disable any further TINT
B tint_end_end
;******END OF ISR*****
tint_end_isr:
ORM #0008H,IMR ;enable timer interrupt
STM #0FFFFH,IFR ;clear any pending interrupts
;***START OF OTHER TINT ISR
tint_end_end:
;***RESTORE CPU REGISTERS
NOP
NOP
POPM AR6
POPM AR5
POPM AR4
POPM AR3
POPM AR2
POPM AR1
POPM ST1
POPM ST0
NOP
NOP
;END OF TIMER ISR
RETE ;enable global INTM
;**************************************************************************
;**************************************************************************
;***
;OTHER SUBROUTINES
;***
;**************************************************************************
; SDA = HIGH ISR
;**************************************************************************
releaseSDA:
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA0)=PCR0
ORM #K_DX_STAT_1, *AR2- ;Mask on DX_STAT BIT
NOP
NOP
RET
;**************************************************************************
; SDA = LOW ISR
;**************************************************************************
pullSDA:
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA0)=PCR0
ANDM #K_DX_STAT_0,*AR2- ;Mask off DX_STAT BIT
NOP
NOP
RET
;**************************************************************************
; SCL = HIGH ISR
;**************************************************************************
releaseSCL:
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA0)=PCR0
ORM #K_FSRP_1,*AR2- ;Mask on FSR BIT
NOP
NOP
RET
;**************************************************************************
; SCL = LOW ISR
;**************************************************************************
pullSCL:
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA0)=PCR0
ANDM #K_FSRP_0,*AR2- ;Mask off FSR BIT
NOP
NOP
RET
;**************************************************************************
;**************************************************************************
;**************************************************************************
; SET MCBSP AS GPIO
;**************************************************************************
_init_gpio:
NOP
PSHM AR2
NOP
STM #SPSA,AR2 ;AR2 points to SPSA0
ST #SPCR2_SUB,*AR2+ ;Sub-bank address (SPSA0)=SPCR20
ST #0000000000000000b,*AR2- ;
;~~~~~~~~~~~~~~~0 (XRST) ;GPIO : transmitter is reset
ST #SPCR1_SUB,*AR2+ ;Sub-bank address (SPSA0)=SPCR20
ST #0000000000000000b,*AR2- ;
;~~~~~~~~~~~~~~~0 (RRST) ;GPIO : receiver set
ST #PCR_SUB,*AR2+ ;Sub-bank address (SPSA0)=PCR0
ST #0011010100100101b,*AR2- ;
;~~1~~~~~~~~~~~~~ (XIOEN) ;GPIO transmitter is enabled
;~~~1~~~~~~~~~~~~ (RIOEN) ;GPIO receiver is enabled
;~~~~0~~~~~~~~~~~ (FSXM) ;FSX set as input
;~~~~~1~~~~~~~~~~ (FSRM) ;FSR set as output
;~~~~~~~1~~~~~~~~ (CLKRM) ;CLKR set as output
;~~~~~~~~~~1~~~~~ (DX_STAT) ;Release SDA line
;~~~~~~~~~~~~~1~~ (FSRP) ;Release SCL line
;~~~~~~~~~~~~~~~1 (CLKRP) ;CLKR = 1
NOP ;McBSP takes 2 clock cycle
NOP ;to start
POPM AR2
NOP
RET
;*************************************************************************
;*************************************************************************
;*************************************************************************
; INITIATE I2C
;*************************************************************************
_init_i2c:
NOP
PSHM AR1
NOP
STM #_I2CSTATUS,AR1
ST #(K_RESET_I2C|K_CSDA_1|K_CSCL_1),*AR1+ ;I2CSTATUS
ST #0,*AR1+ ;ODBYTECTR
ST #7,*AR1+ ;ODBITCTR
ST #0,*AR1+ ;IDBYTECTR
ST #7,*AR1+ ;IDBITCTR
ST #0,*AR1+ ;ERRORCODE
ST #K_SLAVEADDR,*AR1 ;SLAVE_ADDR
NOP
;************************************************************************
; INIT TIMER
;************************************************************************
STM #STOP_TIMER,TCR ;stop timer
STM #K_PRD_VAL,PRD ;load PRD
STM #START_TIMER,TCR ;start timer
ORM #0008H,*(IMR) ;enable timer interrupt
STM #0FFFFH,IFR ;clear any pending interrupts
NOP
POPM AR1
NOP
RET
;***********************************************************************
;***********************************************************************
;***********************************************************************
; INIT MASTER-TRANSMITTER PROCESS
;***********************************************************************
_write_i2c:
NOP
PSHM AR1
PSHM AR2
NOP
STM #_I2CSTATUS,AR1 ;Init i2cstatus register for write
ST #(K_START_1|K_WRITE_TO_SLAVE|K_ADDR_1|K_CSDA_1|K_CSCL_1),*AR1
NOP
STM #_SLAVE_ADDR,AR1 ;1ST loc of ODPTR is slave address
LD *AR1,1,A ;Shift slave address 1 place to the left
ADD #K_I2C_WRITE,A ;Write mode of operation to LSB
STM #_ODPTR,AR2
STL A,*AR2 ;Store back to _ODPTR
STM #_ODBYTECTR,AR1
ADDM #1,*AR1 ;Add one more byte for slave address
NOP
POPM AR2
POPM AR1
NOP
RETE
;************************************************************************
;************************************************************************
;************************************************************************
; INIT MASTER-RECEIVER PROCESS
;************************************************************************
_read_i2c:
NOP
PSHM AR1
NOP
STM #_I2CSTATUS,AR1 ;Init i2cstatus register for read
ST #(K_START_1|K_READ_FROM_SLAVE|K_ADDR_1|K_CSDA_1|K_CSCL_1),*AR1
NOP
STM #_SLAVE_ADDR,AR1 ;1ST loc of ODPTR is slave address
LD *AR1,1,A ;Shift slave address 1 place to the left
ADD #K_I2C_READ,A ;Write mode of operation to LSB
STM #_ODPTR,AR1
STL A,*AR1 ;Store back to _ODPTR
NOP
STM #_ODBYTECTR,AR1 ;Only 1 byte(slave addr) to be send
ST #2,*AR1 ;Must store 1+1 num of bytes
NOP
POPM AR1
NOP
RETE
;************************************************************************
;**************END*OF*FILE***********************************************
;************************************************************************
.end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?