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

📄 vi2c_asm.asm

📁 周立功I2c软件包.rar
💻 ASM
字号:
;--------------------------------------------------------------------------------------------------------
;VI2C_ASM.ASM
;I2C 软件包的底层子程序,使用前要定义好SCL和SDA。在标准80C51模式
;(12 Clock)下,对主频要求是不高于12MHz(1个机器周期1us);若Fosc>12MHz
;则要增加相应的NOP指令数。在使用本软件包时,请在你的程序的未尾加入
;$INCLUDE (VI2C_ASM.ASM)即可。
;--------------------------------------------------------------------------------------------------------
;启动I2C总线子程序      
START:    SETB  SDA
          NOP
          SETB  SCL     			 ;起始条件建立时间大于4.7us
          NOP
          NOP
          NOP
          NOP
          NOP
          CLR  SDA      
          NOP           		 	;起始条件锁定时大于4us
          NOP
          NOP
          NOP
          NOP
          CLR   SCL     		 	;钳住总线,准备发数据
          NOP
          RET

;结束总线子程序
STOP:     CLR    SDA
          NOP
          SETB   SCL    			;发送结束条件的时钟信号
          NOP           			;结束总线时间大于4us
          NOP            
          NOP
          NOP
          NOP
          SETB  SDA    			;结束总线
          NOP          			;保证一个终止信号和起始信号的空闲时间大于4.7us
          NOP
          NOP
          NOP
          RET

;发送应答信号子程序
MACK:     CLR  	SDA      		;将SDA置0 
          NOP
          NOP
          SETB 	SCL
          NOP            			;保持数据时间,即SCL为高时间大于4.7us
          NOP
          NOP
          NOP
          NOP
          CLR  	SCL
          NOP
          NOP
          RET

;发送非应答信号
MNACK:  SETB 	SDA          	;将SDA置1 
          NOP
          NOP
          SETB 	SCL
          NOP
       	  NOP               		;保持数据时间,即SCL为高时间大于4.7us
          NOP
          NOP
          NOP
          CLR  SCL
          NOP
          NOP
          RET

; 检查应答位子程序
; 返回值,ACK=1时表示有应答
CACK:	SETB  SDA
        NOP
        NOP
        SETB  SCL
        CLR   ACK
        NOP
        NOP
        MOV  C,SDA
        JC    CEND
        SETB  ACK           		 ;判断应答位
CEND:	NOP
        CLR  SCL
        NOP
        RET

;发送字节子程序
;字节数据放入ACC       
;每发送一字节要调用一次CACK子程序,取应答位            
WRBYTE: MOV  R0,#08H
WLP: 	RLC   A              		;取数据位
        JC     WR1
        SJMP  WR0            		;判断数据位
WLP1:   DJNZ  R0,WLP
        NOP
        RET
WR1:    SETB  SDA            		;发送1
        NOP
        SETB  SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR   SCL
        SJMP  WLP1
WR0:  	CLR   SDA            		;发送0
        NOP
        SETB  SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR  SCL
        SJMP WLP1

;读取字节子程序                    
;读出的值在ACC
;每取一字节要发送一个应答/非应答信号 
RDBYTE: MOV  R0,#08H
RLP:    SETB  SDA
        NOP
        SETB  SCL         		 ;时钟线为高,接收数据位
        NOP
        NOP
        MOV  C,SDA        		 ;读取数据位
        MOV  A,R2
        CLR   SCL          		 ;将SCL拉低,时间大于4.7us
        RLC   A            		 ;进行数据位的处理
        MOV  R2,A
        NOP
        NOP
        NOP
        DJNZ  R0,RLP        		 ;未够8位,再来一次
        RET

; 无子地址器件写字节数据
; 入口参数: 数据为ACC、器件从地址SLA              
; 占用:  A、R0、CY
IWRBYTE: PUSH   ACC
IWBLOOP: LCALL  START      		;起动总线
         MOV    A,SLA  
         LCALL  WRBYTE     		;发送器件从地址 
         LCALL  CACK
         JNB     ACK,RETWRB      ;无应答则跳转
         POP     ACC       		;写数据
         LCALL  WRBYTE
         LCALL  CACK
         LCALL  STOP
         RET
RETWRB:  POP     ACC
         LCALL  STOP
         RET

;无子地址器件读字节数据
;入口参数: 器件从地址SLA
;出口参数: 数据为ACC    
;占用 A 、R0、R2 、CY
IRDBYTE: LCALL  START
         MOV    A,SLA        		;发送器件从地址
         INC     A
         LCALL  WRBYTE
         LCALL  CACK
         JNB     ACK,RETRDB             
         LCALL  RDBYTE       	;进行读字节操作
         LCALL  MNACK          	;发送非应信号
RETRDB:  LCALL  STOP             	;结束总线
         RET

;向器件指定子地址写N个数据
;入口参数:  器件从地址SLA、器件子地址SUBA 、发送数据缓冲区MTD、发送字节数NUMBYTE
; 占用:  A 、R0 、R1 、R3 、CY 
IWRNBYTE: MOV    A,NUMBYTE
          MOV    R3,A
          LCALL  START        	;起动总线
          MOV    A,SLA
          LCALL  WRBYTE       	;发送器件从地址      
          LCALL  CACK
          JNB     ACK,RETWRN	 ;无应答则退出
          MOV    A,SUBA       	 ;指定子地址 
          LCALL  WRBYTE
          LCALL  CACK
          MOV    R1,#MTD
WRDA:     MOV    A,@R1
          LCALL  WRBYTE       	;开始写入数据
          LCALL  CACK
          JNB     ACK,IWRNBYTE
          INC     R1
          DJNZ    R3,WRDA      	;判断写完没有
RETWRN:   LCALL  STOP
          RET

;向器件指定子地址读取N个数据
;入口参数:  器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数:  接收数据缓冲区MTD
;占用:A、 R0、 R1、 R2、 R3、 CY               
IRDNBYTE:  MOV    R3,NUMBYTE
           LCALL  START
           MOV    A,SLA
           LCALL  WRBYTE        ;发送器件从地址
           LCALL  CACK
           JNB     ACK,RETRDN
           MOV    A,SUBA        	;指定子地址    
           LCALL  WRBYTE
           LCALL  CACK  
           LCALL  START         	;重新起动总线
           MOV    A,SLA
           INC     A             	;准备进行读操作 
           LCALL  WRBYTE
           LCALL  CACK
           JNB     ACK,IRDNBYTE           
           MOV    R1,#MRD
RDN1:      LCALL  RDBYTE      	;读操作开始
           MOV    @R1,A
           DJNZ    R3,SACK
           LCALL  MNACK       	;最后一字节发非应答位               
RETRDN:    LCALL  STOP 			;并结束总线
           RET
SACK:      LCALL  MACK
           INC     R1
           SJMP   RDN1
;*********************************************************************************************
;                         请注意
;
;占用内部资源:         R0,R1,R2,R3,ACC,Cy。
;    在你的程序里要做以下定义:
;使用前须定义变量:  SLA 器件从地址  SUBA器件子地址  NUMBYTE读/写的字节数 ,位变量ACK 
;使用前须定义常量:  SDA SCL 总线位  MTD 发送数据缓冲区首址    MRD 接收数据缓冲区首址
;(ACK为调试/测试位,ACK为0时表示无器件应答)
;
;**********************************************************************************************






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -