⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlg500s_i2c.asm

📁 zlg500S 刷卡机 I2C 总线51程序
💻 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 + -