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

📄 fm24c04.asm

📁 本程序为集中抄表系统中低压电力线载波数据采集器程序源代码
💻 ASM
字号:
;-----------------------------------------------
;存储器FM24C04读写子程序
;-----------------------------------------------
;从C04中读1个字节
;-----------------------------------------------
;入口:DPH(SLAVE编码地址),DPL(SLAVE中待写入数据的地址)
;占用:R2,R3,R4,A
;出口:B(读的数据)
;-----------------------------------------------
;C04_ADDR_L	EQU	0A0H				;0A0H中高7位有效,C04的00H-0FFH部分芯片地址
;C04_ADDR_H	EQU	0A2H				;0A2H中高7位有效,C04的100H-1FFH部分芯片地址
;-----------------------------------------------
RD_C04_1BYTE:
		LCALL	RD_SLAVE_ONE_BYTE
		MOV	R4,B
		LCALL	RD_SLAVE_ONE_BYTE
		MOV	A,B
		CJNE	A,04H,RD_C04_1BYTE
		RET
;-----------------------------------------------
;--向C04中写入1个字节
;-----------------------------------------------
;入口:DPH(SLAVE编码地址),DPL(SLAVE中待写入数据的地址),B(待写入的数据)
;占用:R2,R3,R4,A
;-----------------------------------------------
;C04_ADDR_L	EQU	0A0H				;0A0H中高7位有效,C04的00H-0FFH部分芯片地址
;C04_ADDR_H	EQU	0A2H				;0A2H中高7位有效,C04的100H-1FFH部分芯片地址
;-----------------------------------------------
WR_C04_1BYTE:
		LCALL	WR_SLAVE_ONE_BYTE
		MOV	R4,B
		LCALL	RD_SLAVE_ONE_BYTE
		MOV	A,B
		CJNE	A,04H,WR_C04_1BYTE
		RET
;--------------------------------------
;写入任意地址一个字节
;入口:DPH(SLAVE编码地址),DPL(SLAVE中待写入数据的地址),B(待写入的数据),
;占用:R2,R3,A
;--------------------------------------
;SLAVE_ANSWER_OK	BIT 20H.7                            ;读写ST7536的SRAM正常应答与否的判断
;SDA1			BIT P1.3                             ;SLAVE内部I2C总线数据线
;SCL1			BIT P1.2                             ;SLAVE内部I2C总线时钟线
;--------------------------------------
WR_SLAVE_ONE_BYTE:
                MOV	R3,#9
WR_SLAVE_ONE_BYTE0:
		LCALL   SLAVE_I2C_START                  ;产生起动信号
                MOV     A,DPH
                LCALL   WR_SLAVE_ADDR                    ;发送7位从器件地址码#B0H
                LCALL   SEND_WR_BIT_0                    ;发送写控制位0
                LCALL   CHK_SLAVE_ACK                    ;CPU等待SLAVE的应答确认信号
                MOV     C,SLAVE_ANSWER_OK                ;SLAVE应答位
                JNC     WR_NEXT1                         ;为0表示正确应答1表示无应答
                LCALL   SLAVE_I2C_STOP                   ;CPU停止操做
                DJNZ	R3,WR_SLAVE_ONE_BYTE0            ;SLAVE没正确收到起始位,CPU需重发
		RET
WR_NEXT1:       MOV     A,DPL                            ;要写入字节的地址
                LCALL   WR_S_BYTE_ADDR                   ;发送8位单字节
                LCALL   CHK_SLAVE_ACK                    ;检测应答位
                MOV     C,SLAVE_ANSWER_OK
                JNC     WR_NEXT2
                LCALL   SLAVE_I2C_STOP
		DJNZ	R3,WR_SLAVE_ONE_BYTE0              ;SLAVE没正确收到起始位,CPU需重发
		RET
WR_NEXT2:       MOV     A,B                                ;要写的数据
                LCALL   WR_S_DATA
                LCALL   CHK_SLAVE_ACK
                MOV     C,SLAVE_ANSWER_OK
                JNC     WR_NEXT3
                LCALL   SLAVE_I2C_STOP                   ;发送停止位
		DJNZ	R3,WR_SLAVE_ONE_BYTE0            ;SLAVE没正确收到起始位,CPU需重发
		RET
WR_NEXT3:       LCALL   SLAVE_I2C_STOP
                RET
;---------------------------------------
;读任意地址一个字节;
;入口:DPH(SLAVE编码地址),DPL(SLAVE中待读出数据的地址)
;占用:R2,R3,A
;出口:B(读出的数据)
;--------------------------------------
RD_SLAVE_ONE_BYTE:
                MOV	R3,#9
RD_SLAVE_ONE_BYTE0:
		LCALL   SLAVE_I2C_START                  ;第一次产生起动信号
                MOV     A,DPH
                LCALL   WR_SLAVE_ADDR                    ;发送7位从器件地址码#B0H
                LCALL   SEND_WR_BIT_0                    ;发送写控制位0                           ;读控制字
                LCALL   CHK_SLAVE_ACK                    ;检测应答
                MOV     C,SLAVE_ANSWER_OK
                JNC     RD_NEXT1
                LCALL   SLAVE_I2C_STOP
		DJNZ	R3,RD_SLAVE_ONE_BYTE0            ;SLAVE没正确收到起始位
		RET
RD_NEXT1:       MOV     A,DPL
                LCALL   WR_S_BYTE_ADDR                   ;写入地址
                LCALL   CHK_SLAVE_ACK
                MOV     C,SLAVE_ANSWER_OK
                JNC     RD_NEXT2
                LCALL   SLAVE_I2C_STOP
		DJNZ	R3,RD_SLAVE_ONE_BYTE0            ;SLAVE没正确收到起始位
		RET
RD_NEXT2:       LCALL   SLAVE_I2C_START                  ;第2产生起动信号
                MOV     A,DPH
                LCALL   WR_SLAVE_ADDR                    ;发送7位从器件地址码#B0H
                LCALL   SEND_RD_BIT_1                    ;发送读控制位1
                LCALL   CHK_SLAVE_ACK
                MOV     C,SLAVE_ANSWER_OK
                JNC     RD_NEXT3
                LCALL   SLAVE_I2C_STOP
		DJNZ	R3,RD_SLAVE_ONE_BYTE0            ;SLAVE没正确收到起始位
		RET
RD_NEXT3:       LCALL   RD_S_DATA
                MOV     B,A
                LCALL   SEND_NOACK_BIT
                LCALL   SLAVE_I2C_STOP
                RET
;---------------------------------
;接收单字节;
;---------------------------------
RD_S_DATA:	MOV     R2,#08H
RLP:            SETB    SDA1                        ;置数据线为高电平,输入状态
		NOP
                NOP
		NOP
		SETB    SCL1                        ;置高时钟线,禁止数据变化
                NOP
		JNB     SDA1,RD0                    ;转读入0
RD1:            SETB    C                           ;读入1
                RLC     A
                CLR     SCL1                        ;允许数据变化,输入下一位
RLP1:           DJNZ    R2,RLP
                RET
RD0:            CLR     C                                  ;读入0
                RLC     A
                CLR     SCL1                        ;允许数据变化,输入下一位
                SJMP    RLP1
;---------------------------------
;发送单字节
;入口:A(向从器件写入的数据,高位先写)
;占用:R2
;---------------------------------
WR_SLAVE_ADDR:	MOV     R2,#07H                            ;发送SLAVE从器件地址码为7位
                SJMP    WRITE_S_LOOP
WR_S_BYTE_ADDR:
WR_S_DATA:	MOV     R2,#08H                            ;其它字节为8位
WRITE_S_LOOP:	CLR     SCL1
		RLC     A                                  ;循环左移
                JC      WRITE_S_1                          ;写1转
WRITE_S_0:	CLR     SDA1                               ;发送0
                SETB    SCL1
                NOP
                NOP
                NOP
		CLR     SCL1
		SETB	SDA1
WRITE_S_LOOP1:	DJNZ    R2,WRITE_S_LOOP
                RET
WRITE_S_1:	SETB    SDA1                        ;发送1
                SETB    SCL1
                NOP
		NOP
                NOP
                CLR     SCL1                        ;脉冲线负跳变,把数据位发出
                SJMP    WRITE_S_LOOP1
;---------------------------------------------
;CPU对SLAVE的I2C操作起动信号;
;产生条件:时钟为高,数据线上产生由高到低的跳变;
;---------------------------------------------
SLAVE_I2C_START:
		CLR     SCL1                                  ;时钟线低
                SETB    SDA1                                  ;数据线高
                SETB    SCL1                                  ;时钟线高
                NOP
                NOP
                CLR     SDA1                                  ;数据线由高到低
                NOP
                NOP
                CLR     SCL1                                  ;时钟线低
                RET
;--------------------------------------------
;停止信号;
;产生条件:时钟为高,数据线上产生由低到高的跳变;
;--------------------------------------------
SLAVE_I2C_STOP:
		CLR     SCL1                                  ;时钟线低
                CLR     SDA1
                SETB    SCL1
                NOP
                NOP
                SETB    SDA1
                NOP
                NOP
                CLR     SCL1
                RET
;-----------------------------------
;发送读写控制位
;-----------------------------------
SEND_RD_BIT_1:	SETB  SDA1
		SJMP  SEND_WR_BIT
SEND_WR_BIT_0:	CLR   SDA1
SEND_WR_BIT:	SETB  SCL1
		NOP
		NOP
		NOP
		CLR    SCL1
		SETB   SDA1
		RET
;-----------------------------------
;读时CPU发送应答位:0
;产生条件:时钟为高电平期间,拉数据线为稳定的低电平
;-----------------------------------
SEND_ACK_BYT:   CLR     SDA1
                SETB    SCL1
                NOP
                NOP
                CLR     SCL1
                SETB    SDA1
                RET
;-------------------------------------
;发送非应答位:1
;产生条件:时钟为高电平期间,拉数据线为稳定的高电平
;-------------------------------------
SEND_NOACK_BIT: SETB    SDA1
                SETB    SCL1
                NOP
                NOP
		NOP
                CLR     SCL1
                RET
;-------------------------------------
;检测SLAVE应答位;
;SLAVE_ANSWER_OK=0,有正常应答
;SLAVE_ANSWER_OK=1,无应答
;-------------------------------------
CHK_SLAVE_ACK:	SETB    SDA1                                  ;数据线上送一高电平
		NOP
		NOP
		NOP
		SETB    SCL1
                CLR     SLAVE_ANSWER_OK                         ;清有应答表志
		JNB     SDA1,CHK_S_END                          ;检测数据线是否变低
                SETB    SLAVE_ANSWER_OK                         ;变低表示SLAVE有应答则置位有应答表志
CHK_S_END:	CLR     SCL1
                NOP
                NOP
                SETB	SDA1
		RET

⌨️ 快捷键说明

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