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

📄 24c04

📁 RM51单片机实验板配套实验例程库
💻
字号:

;****************************************************************
;*      ★★★          24C04存储器读写实验         ★★★      *
;* (电子驿站单片机实验板、开发板配套例程,程序转载请著明出处。) *
;*  E-mail: support@ourmpu.com   QQ留言:451338254 476485321    *
;*  编程:ourmpu  http://www.ourmpu.com/ 更多例程请登陆网站     *
;****************************************************************
;*  每次上电24C04的00H单元值自动加1,其值从00H~FFH,即从0~255 *
;*  上电次数值显示在数码管中,数码管第1位和第2位显示十六进制值  *
;*  数码管第4~6位显示的是计数值,即对应的BCD值0~255           *
;*  可以直观地看到十六进制和BCD值的对应关系         *
;*  试验时按压实验板电源开关,关闭实验板电源,再次开启电源时,数码管显示值加1   *
;*  按压复位按钮可以模拟断电过程,计数值也自动加1               *
;*  写入24C04的数据断电能够长期保存,适合用来存储系统的一些参数 *
;****************************************************************
		
	ORG	0000H
	AJMP	START

	ORG	0033H
START:	
	SDA	BIT	P1.1
	SCL	BIT	P1.0
	ACK   	BIT  	00H    	;24C04应答标志位
	I2C_ERR	BIT	01H	;I2C读写出错标志
	
	AT24C04	EQU  	0A0H	;24C04硬件地址(低256字节)
	SLA   	EQU 	30H	;器件硬件地址
      	SUBA  	EQU 	31H	;器件字节地址
      	DANUM	EQU	32H	;
      NUMBYTE  	EQU 	33H	;读/写的字节数
      	MTD	EQU   	34H	;待发送数据缓冲区指针,MTD里存储数据块首址
      	MRD	EQU   	35H 	;待接收数据缓冲区指针,MRD里存储数据块首址
      	DIS1	EQU	36H	;
      	DIS2	EQU	37H
      	DIS3	EQU	38H
      	DIS4	EQU	39H
      	DIS5	EQU	3AH
      	DIS6	EQU	3BH
					
	MOV	SP,#50H
	MOV	P0,#0FFH
	MOV	P1,#0FFH
	MOV	P2,#0FFH
	MOV	P3,#0FFH
	
;--------- 读1字节,读出的数据在DANUM中 ----------
READ:	MOV	SLA,#AT24C04	;24C04硬件地址
	MOV	SUBA,#00H	;24C04的00H单元
	MOV	MRD,#DANUM	;读出的数据存入单元
	MOV	NUMBYTE,#1	;读出1位数据
	ACALL	IRDNBYTE	;读数操作
	
	MOV	A,DANUM		;十六进制显示第一位
	SWAP	A
	ANL	A,#00001111B
	MOV	DIS1,A
	
	MOV	A,DANUM		;十六进制显示第二位
	ANL	A,#00001111B
	MOV	DIS2,A
	
	MOV	A,DANUM
	MOV 	B,#100 		;分离出百位
	DIV 	AB
	MOV 	DIS4,A		;上电次数百位
	MOV 	A,#10
	XCH 	A,B
	DIV 	AB
	MOV 	DIS6,B		;上电次数十位
	MOV 	DIS5,A		;上电次数个位
	
	MOV	A,DANUM
	INC	A	
	MOV	DANUM,A
	
;--------- 写1字节,待写入的数据在DANUM中 ----------				
WRITE:	MOV	SLA,#AT24C04	;24C04硬件地址(低256字节)
	MOV	SUBA,#00H	;数据存入24C04的00H(起始单元)
	MOV	MTD,#DANUM	;待存数据块首址指针
	MOV	NUMBYTE,#1	;写入1位数据
	ACALL	IWRNBYTE	;把数据存入24C04
	ACALL	YS18ms		;延时18ms,等待24C04写周期结束
		
MAIN:	MOV	A,DIS1
	MOV	DPTR,#SGTB
	MOVC	A,@A+DPTR
	MOV	P0,A
	SETB	P2.0
	SETB	P2.1
	SETB	P2.2
	SETB	P2.3
	SETB	P2.4
	CLR	P2.5
	ACALL	DELAY

	MOV	A,DIS2
	MOV	DPTR,#SGTB
	MOVC	A,@A+DPTR
	MOV	P0,A
	SETB	P2.0
	SETB	P2.1
	SETB	P2.2
	SETB	P2.3
	CLR	P2.4
	SETB	P2.5
	ACALL	DELAY
	
	MOV	A,DIS4
	MOV	DPTR,#SGTB
	MOVC	A,@A+DPTR
	CJNE	A,#0C0H,NEXT
	MOV	A,#0FFH
NEXT:	MOV	P0,A
	SETB	P2.0
	SETB	P2.1
	CLR	P2.2
	SETB	P2.3
	SETB	P2.4
	SETB	P2.5
	ACALL	DELAY
	
	MOV	A,DIS5
	MOV	DPTR,#SGTB
	MOVC	A,@A+DPTR
	MOV	B,A
	MOV	A,DIS4
	CJNE	A,#00H,NEXT1
	MOV	A,B
	CJNE	A,#0C0H,NEXT2
	MOV	A,#0FFH
	AJMP	NEXT2
NEXT1:	MOV	A,B
NEXT2:	MOV	P0,A
	SETB	P2.0
	CLR	P2.1
	SETB	P2.2
	SETB	P2.3
	SETB	P2.4
	SETB	P2.5
	ACALL	DELAY
	
	MOV	A,DIS6
	MOV	DPTR,#SGTB
	MOVC	A,@A+DPTR
	MOV	P0,A
	CLR	P2.0
	SETB	P2.1
	SETB	P2.2
	SETB	P2.3
	SETB	P2.4
	SETB	P2.5
	ACALL	DELAY

	AJMP	MAIN

;-----------------------------------------------------------
;单字节十六进制整数转换成单字节BCD码整数
;入口条件:待转换的单字节十六进制整数在累加器A中。
;出口信息:转换后的BCD码整数(十位和个位)仍在累加器A中,百位在R3中。
;影响资源:PSW、A、B、R3 堆栈需求: 2字节

HBCD: 	MOV 	B,#100 		;分离出百位,存放在R3中
	DIV 	AB
	MOV 	DIS3,A
	MOV 	A,#10 		;余数继续分离十位和个位
	XCH 	A,B
	DIV 	AB
	MOV 	DIS4,B
	MOV 	DIS5,A
;	SWAP 	A
;	ORL 	A,B 		;将十位和个位拼装成BCD码
	RET
			
;********** I2C总线24C04读写程序 *********** 
;启动I2C总线子程序      
STA:   	SETB  	SDA
        NOP
        SETB  	SCL		;起始条件建立时间大于4.7us
        JNB	SDA,X10		;SDA=\1则有错
        JNB	SCL,X10		;SCL=\1则有错
        NOP
        CLR  	SDA     
        NOP           		;起始条件锁定时大于4us
        NOP
        NOP
        NOP
        NOP
        CLR   	SCL     	;钳住总线,准备发数据
       	CLR	I2C_ERR		;总线正确,清出错标志  
	AJMP	X11
X10:	SETB	I2C_ERR		;总线出错,置出错标志
X11:    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

;向器件指定子地址写N个数据
;入口参数:  器件从地址SLA、器件子地址SUBA 、发送数据缓冲区MTD、发送字节数NUMBYTE
; 占用:  A 、R0 、R1 、R3 、CY 
IWRNBYTE:
	CLR	EA		;关闭中断
	MOV    	A,NUMBYTE
        MOV    	R3,A
        ACALL  	STA           	;起动总线
        MOV    	A,SLA
        ACALL  	WRBYTE       	;发送器件从地址      
        ACALL  	CACK
        JNB    	ACK,WRNERR	;无应答则退出
        MOV    	A,SUBA        	;指定子地址 
	ACALL  	WRBYTE
	ACALL  	CACK
	MOV    	R1,MTD
WRDA:   MOV    	A,@R1
        ACALL  	WRBYTE       	;开始写入数据
        ACALL  	CACK
        JNB    	ACK,IWRNBYTE
        INC    	R1
        DJNZ   	R3,WRDA      	;判断写完没有
        SJMP	RETWRN		;正确写入退出
WRNERR: SETB	I2C_ERR	;置出错标志
RETWRN: ACALL  	STOP
        SETB	EA		;开中断
        RET

;向器件指定子地址读取N个数据
;入口参数:  器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数:  接收数据缓冲区MRD
;占用:A、 R0、 R1、 R2、 R3、 CY               
IRDNBYTE:
	CLR	EA		;关中断
	MOV    	R3,NUMBYTE
        ACALL  	STA
        MOV    	A,SLA
        ACALL  	WRBYTE    	;发送器件从地址
        ACALL  	CACK
        JNB    	ACK,RDNERR
        MOV    	A,SUBA       	;指定子地址    
        ACALL  	WRBYTE
        ACALL  	CACK  
        ACALL  	STA         	;重新起动总线
        MOV    	A,SLA
	INC    	A             	;准备进行读操作 
	ACALL  	WRBYTE
	ACALL  	CACK
	JNB    	ACK,IRDNBYTE           
        MOV    	R1,MRD
RDN1:   ACALL  	RDBYTE      	;读操作开始
        MOV    	@R1,A
        DJNZ   	R3,SACK
        ACALL  	MNACK       	;最后一字节发非应答位
        SJMP	RETRDN		;读正常退出
RDNERR:	SETB	I2C_ERR		;置出错标志
RETRDN: ACALL  	STOP 		;并结束总线
    	SETB	EA		;开中断
    	RET
SACK:   ACALL  	MACK
        INC    	R1
        SJMP	RDN1

;************* 8位共阳数码管字型表 *****************
SGTB:	DB	0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
	DB	88H,83H,0C6H,0A1H,86H,8EH,89H,0A3H,8CH,0C8H

;********  延时子程序  ********
DELAY:	MOV	R1,#10
Y1:	MOV	R2,#100
	DJNZ	R2,$
	DJNZ	R1,Y1
	RET

;------------- 延时18ms -------------
YS18ms:	MOV	R6,#40		;准备延时18888us
	AJMP	Y3		;开始延时			
YS4722U:MOV	R6,#10 		;延时4722微秒
Y3: 	MOV	R5,#216		;[1]
	DJNZ	R5,$		;[2]
	DJNZ	R6,Y3 		;[2]
	RET			;[1]

	END

⌨️ 快捷键说明

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