?? i2c.asm
字號:
.mmregs
.include "time.inc"
.include "i2c.inc"
.include "bsp.inc"
.include "i2creg.inc"
.def TIMER_INT
.def _I2CSTATUS,_ODBYTECTR,_IDBYTECTR,_ODPTR,_SLAVE_ADDR
.def _init_gpio,_init_i2c,_write_i2c,_read_i2c
.ref _USER_FUNCTION
;***字節位屏蔽
.sect "constant"
MASK .int 01h ;Bit 0
.int 02h ;Bit 1
.int 04h ;Bit 2
.int 08h ;Bit 3
.int 10h ;Bit 4
.int 20h ;Bit 5
.int 40h ;Bit 6
.int 80h ;Bit 7 (MSB)
.sect "program"
;***************************************************************************
; 定時中斷服務函數
;***************************************************************************
TIMER_INT:
;***寄存器壓棧***
NOP
NOP
PSHM ST0
PSHM ST1
PSHM AR1
PSHM AR2
PSHM AR3
PSHM AR4
PSHM AR5
PSHM AR6
NOP
NOP
RSBX SXM
RSBX CPL
RSBX HM
LD #_I2C_DP,DP
NOP
NOP
LD _I2CSTATUS,A ;加載I2C狀態
LD A,B ;乘2
AND #K_DISABLE_I2C,B ;檢測I2C是否使能
BC tint_disable_tint,BNEQ ;如果 =1, 結束
;***更新 前位SDA和SCL***
AND #3H,A
LD A,2,B
ANDM #0FFF0H,_I2CSTATUS
LD _I2CSTATUS,A
ADD B,A
STL A,_I2CSTATUS
;***更新當前 SDA 和 SCL***
STM #SPSA,AR2
ST #PCR_SUB,*AR2+
LD #(K_DR_STAT_1|K_FSXP_1),B
AND #0FFFFH,A
AND *AR2-,B
OR B,-3,A
STL A,_I2CSTATUS
;***檢測開始/結束條件或操作模式 ***
LD A,B
AND #K_CLKH_1,B
BC tint_clk_go_high,BNEQ
LD A,B
AND #K_CLKL_1,B
BC tint_clk_go_low,BNEQ
LD A,B ;乘2左移
AND #K_ACK_1,B
BC tint_ack,BNEQ ;應答?
LD A,B ;左移
AND #K_START_1,B ;起始狀態?
BC tint_start,BNEQ
AND #K_STOP_1,A ;結束?
BC tint_stop,ANEQ
MVDK _I2CSTATUS,TEMP_REG
ANDM #01100000B, TEMP_REG
CMPM TEMP_REG,#K_READ_FROM_SLAVE
BC tint_read_slave, TC
CMPM TEMP_REG,#K_WRITE_TO_SLAVE
BC tint_write_slave, TC
B tint_busy
;**************************************************************************
;**************************************************************************
;*****起始條件預處理*****
tint_start:
;***讀當前或前一 SDA/SCL 幅值***
MVDK _I2CSTATUS,TEMP_REG
ANDM #0FH, TEMP_REG
CMPM TEMP_REG,#1111B
BC tint_start_start,TC
CMPM TEMP_REG,#1110B
;1~~~
;~1~~
;~~1~
;~~~0
BC tint_start_finish,TC
B tint_start_invalid
;***開始起始條件***
tint_start_start:
CALL pullSDA ;SDA->0 當 SCL=1
;***計時5us
STM #STOP_TIMER,TCR
STM #K_START_HOLD_TIME,PRD
STM #START_TIMER,TCR ;開始計時
B tint_end_isr
;***結束起始條件***
tint_start_finish:
CALL pullSCL
ANDM #K_START_0,_I2CSTATUS
ST #1,TEMP_REG
B tint_end_isr
;***狀態未知***
tint_start_invalid:
CALL releaseSDA ;釋放數據時鐘線,重新開始
CALL releaseSCL
B tint_end_isr
;**************************************************************************
;**************************************************************************
;******開始應答位部分*****
tint_ack:
;***是否主接收模式?(read slave)
MVDK _I2CSTATUS,TEMP_REG
ANDM #01100000B, TEMP_REG
CMPM TEMP_REG,#K_READ_FROM_SLAVE
BC tint_ack_not_rs, NTC
LD _I2CSTATUS,A
AND #K_ADDR_1,A
BC tint_ack_end_slave_addr,ANEQ
LD POINTER,B
BC tint_ack_rs_first,BEQ
CALL releaseSDA
ANDM #K_ACK_0,_I2CSTATUS
B tint_end_isr
tint_ack_rs_first:
ST #1,POINTER
LD _I2CSTATUS,A
AND #K_STOP_1,A
BC tint_ack_stop,ANEQ
CALL pullSDA
B tint_ack_end
tint_ack_stop:
CALL releaseSDA
B tint_ack_end
tint_ack_end_slave_addr:
ANDM #K_ADDR_0,_I2CSTATUS
;***主機發送模式 (write slave)***
tint_ack_not_rs:
CALL releaseSDA
ST #0,TEMP_REG
tint_ack_end:
ORM #K_CLKH_1,_I2CSTATUS
B tint_end_isr
;***是否從給主應答***
tint_ack_test:
;ST SPSA,AR2
ST #PCR_SUB,*AR2+
LD #K_FSXP_1,A
AND *AR2-,A
BC tint_ack_sda_low,AEQ
;***從機沒應答***
ORM #K_ERR_1,_I2CSTATUS
ST #K_ERR_NOACK,ERRORCODE
tint_ack_sda_low:
;***從機應答***
ORM #K_CLKL_1,_I2CSTATUS
ANDM #(K_ACK_0&K_ADDR_0),_I2CSTATUS
STM #STOP_TIMER,TCR
STM #K_SCL_HIGH,PRD
STM #START_TIMER,TCR
B tint_end_isr
;**************************************************************************
;**************************************************************************
;*****停止條件部分*****
tint_stop:
LD TEMP1_REG,A
BC tint_stop_continue,ANEQ
CALL pullSDA
ST #1,TEMP1_REG
STM #STOP_TIMER,TCR
STM #K_STOP_SETUP_TIME,PRD
STM #START_TIMER,TCR
B tint_end_isr
tint_stop_continue:
MVDK _I2CSTATUS,TEMP_REG
ANDM #03H,TEMP_REG
;***SCL=1 , SDA=0***
CMPM TEMP_REG,#10B
;1~
;~0
BC tint_stop_finish,TC
;*** SCL/SDA=0/0***
CMPM TEMP_REG,#00B
;0~
;~0
BC tint_stop_invalid,NTC
CALL releaseSCL
NOP
NOP
NOP
;***同步***
;ST SPSA,AR2
ST #PCR_SUB,*AR2+
LD #K_DR_STAT_1,A
AND *AR2-,A
BC tint_stop_scl_go_high_yes,ANEQ
;***定時 1us***
B tint_stop_invalid
tint_stop_scl_go_high_yes:
;***定時5us保持時間***
STM #STOP_TIMER,TCR
STM #K_STOP_SETUP_TIME,PRD
STM #START_TIMER,TCR
B tint_end_isr
;***SDA=0 ***
tint_stop_finish:
CALL releaseSDA
ANDM #K_STOP_0,_I2CSTATUS
ORM #K_SUCC_1,_I2CSTATUS
NOP
CALL _USER_FUNCTION
NOP
B tint_end_isr
tint_stop_invalid:
CALL pullSDA
CALL releaseSCL
STM #STOP_TIMER,TCR
STM #K_PRD_VAL,PRD
STM #START_TIMER,TCR
B tint_end_isr
;**************************************************************************
;**************************************************************************
;*****讀從機*****
tint_read_slave:
LD _I2CSTATUS,A
AND #K_ADDR_1,A
BC tint_clk_go_high,AEQ
B tint_write_slave
;***當 SCL=1讀數據***
tint_rs_mode:
;***SETUP POINTERS TO CORRECT LOCATION***
LD #IDPTR,B ;Load addr of out-data to B
LD _IDBYTECTR, -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
CMPM IDBITCTR,#7 ;If IDBITCTR == 7, then it is new byte
BC tint_rs_not_new_byte,NTC ;else not new byte
ST #0,*AR4 ;Clear the memory location
tint_rs_not_new_byte:
ST #PCR_SUB,*AR2+ ;Check current line status of SDA
LD #K_FSXP_1,B ;Mask FSXP bit (bit 3)
AND *AR2-,B ;check FSXP bit
LD B,-3,A ;Store to bit 0 of A
LD IDBITCTR,B ;Check if end of byte,ie. bit ctr=0
BC tint_rs_bit_0,BEQ ;If bit ctr=0, goto new_byte
SUB #1,B ;else decrement bit ctr
STL B,TEMP1_REG ;Store to TEMP1 register
RPT TEMP1_REG ;Shift A (bitctr-1) times
SFTL A,1 ;Result in A
;***LSB NO NEED TO SHIFT***
tint_rs_bit_0: ;If bit 0, no need to shift
LD *AR4,B ;Load B with current read byte
OR A,B ;Combine and store to B
AND #0FFH,B ;Allows only byte
STL B,*AR4 ;Store back to memory
LD IDBITCTR,A ;If BITCTR=0(LSB) ie. end of byte
BC tint_rs_next_byte,AEQ ;goto next byte
SUB #1,A,B ;Decrement A and store to B
STL B,IDBITCTR ;Store back to register
B tint_rs_next ;Next bit
;***TEST IF COME TO LAST BYTE***
tint_rs_next_byte:
ORM #K_ACK_1,_I2CSTATUS ;Enable ACK flag
ST #7,IDBITCTR ;Start from MSB (initiate next byte)
ADDM #1,POINTER ;Increment POINTER
ANDM #0FFH,_IDBYTECTR ;Prepare num of btye to receive
LD POINTER,B ;Load the incremental POINTER to B
LD _IDBYTECTR,A ;Load num of byte to A
SUB B,A ;A=(Num of byte) - (current byte POINTER)
BC tint_rs_no_more_byte,AEQ ;If=0,no more to receive
LD POINTER,8,A ;Shift 8 places forward
LD _IDBYTECTR,B ;
OR B,A ;Combine POINTER and num of btye to send
STL A,_IDBYTECTR ;Update IDBYTECTR
B tint_rs_next ;Goto next byte
tint_rs_no_more_byte:
ORM #K_STOP_1,_I2CSTATUS ;Enable STOP condition
tint_rs_next:
ST #0,POINTER ;Extra flag use in ack_rs
ORM #K_CLKL_1,_I2CSTATUS ;Next TINT,enable releaseSCL
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 ;
;**************************************************************************
;**************************************************************************
;*****WRITE TO SLAVE SEQUENCES*****
tint_write_slave:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -