📄 zlg500s_i2c.asm
字号:
NAME zlg500s_I2C
SDA BIT P1.6 ;090H.6
SCL BIT P1.5 ;090H.5
?PR?_zlg500s_rcv?zlg500s_I2C SEGMENT CODE
?DT?_zlg500s_rcv?zlg500s_I2C SEGMENT DATA OVERLAYABLE
?PR?_zlg500s_send?zlg500s_I2C SEGMENT CODE
?DT?_zlg500s_send?zlg500s_I2C SEGMENT DATA OVERLAYABLE
PUBLIC ?_zlg500s_send?BYTE
PUBLIC _zlg500s_send
PUBLIC ?_zlg500s_rcv?BYTE
PUBLIC _zlg500s_rcv
RSEG ?DT?_zlg500s_rcv?zlg500s_I2C
?_zlg500s_rcv?BYTE:
slv_adr?040: DS 1
databfr?041: DS 1
RSEG ?DT?_zlg500s_send?zlg500s_I2C
?_zlg500s_send?BYTE:
slv_adr?142: DS 1
databfr?143: DS 1
len?144: DS 1
; unsigned char zlg500s_Rcv(unsigned char slv_adr,unsigned char idata *databfr)
RSEG ?PR?_zlg500s_rcv?zlg500s_I2C
_zlg500s_rcv:
MOV A,R5
MOV R0,A
MOV R3,#1
LCALL START ;起动总线
MOV A,R7
SETB ACC.0 ;准备进行读操作
LCALL WRBYTE
LCALL CACK
JC RNACKEXIT
; DB 0,0,0,0,0,0,0,0
CLR F0 ;读数据标志清零
RD3: LCALL RDBYTE ;先读三字节
MOV @R0,A
DJNZ R3,SACK
;JZ SNACK ;数据长度为零则退出
SETB F0 ;读数据标志置位
MOV R3,A
CJNE A,#6,RD1 ;接收数据长度应不小于6
SJMP RD2
RD1: JC RD6 ;小于6,则发送停止位,失败退出
RD2: CJNE A,#37,RD4
SJMP RD5
RD4: JNC RD6 ;数据长度大于37,则发送停止位,失败退出
RD5: DEC R3 ;减去帧长本身
SJMP SACK
RDN1: LCALL RDBYTE ;读数据
MOV @R0,A
DJNZ R3,SACK
SNACK: LCALL MNACK ;最后一字节发非应答位
RETRDN: LCALL STOP ;并结束总线
MOV R7,#1 ;成功返回TRUE
RET
LJMP 0000H
SACK: LCALL MACK
INC R0
JNB F0,RD3
SJMP RDN1
LJMP 0000H
RD6: LCALL STOP
RNACKEXIT:
MOV R7,#0 ;失败返回FALSE
RET
LJMP 0000H
; END OF _zlg500s_rcv
; unsigned char zlg500s_Send(unsigned char slv_adr,unsigned char *databfr,unsigned char len);
RSEG ?PR?_zlg500s_send?zlg500s_I2C
_zlg500s_send:
MOV A,R5
MOV R0,A
LCALL START ;起动总线
MOV A,R7
LCALL WRBYTE ;发送器件从地址
LCALL CACK
JC WNACKEXIT ;无应答则退出
WRDA: MOV A,@R0
LCALL WRBYTE ;开始写入数据
LCALL CACK
JC WNACKEXIT
INC R0
DJNZ R3,WRDA ;判断写完没有
RETWRN: LCALL STOP
MOV R7,#1 ;成功返回TRUE
RET
LJMP 0000H
WNACKEXIT:
MOV R7,#0 ;失败返回FALSE
RET
LJMP 0000H
; END OF _zlg500s_send
START: SETB SDA
NOP
SETB SCL ;起始条件建立时间大于4.7us
JNB SCL,$
CLR SDA
NOP
CLR SCL ;钳住总线,准备发数据
NOP
RET
LJMP 0000H
;结束总线子程序
STOP: CLR SDA
NOP
SETB SCL ;发送结束条件的时钟信号
JNB SCL,$
SETB SDA ;结束总线
NOP ;保证一个终止信号和起始信号的空闲时间大于4.7us
RET
LJMP 0000H
;发送应答信号子程序
MACK: CLR SDA ;将SDA置0
NOP
SETB SCL
JNB SCL,$ ;保持数据时间,即SCL为高时间大于4.7us
CLR SCL
NOP
RET
LJMP 0000H
;发送非应答信号
MNACK: SETB SDA ;将SDA置1
NOP
SETB SCL
JNB SCL,$ ;保持数据时间,即SCL为高时间大于4.7us
; NOP
CLR SCL
RET
LJMP 0000H
; 检查应答位子程序
; 应答位在C中
CACK: SETB SDA
NOP
SETB SCL
JNB SCL,$
MOV C,SDA
; NOP
CLR SCL
NOP
RET
LJMP 0000H
;发送字节子程序
;字节数据放入ACC
;每发送一字节要调用一次CACK子程序,取应答位
WRBYTE: MOV R2,#08H
RLC A
; DB 0,0,0,0
WLP: MOV SDA,C
SETB SCL
JNB SCL,$
RLC A
CLR SCL
DJNZ R2,WLP
RET
LJMP 0000H
;读取字节子程序
;读出的值在ACC
;每取一字节要发送一个应答/非应答信号
RDBYTE: MOV R2,#08H
SETB SDA
; DB 0,0,0,0,0,0,0,0
; DB 0,0,0,0 ;,0,0,0,0
RLP: SETB SCL ;时钟线为高,接收数据位
JNB SCL,$
MOV C,SDA ;读取数据位
RLC A
CLR SCL ;将SCL拉低,时间大于4.7us
DJNZ R2,RLP ;未够8位,再来一次
RET
LJMP 0000H
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -