📄 fm24c04.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 + -