📄 实验十一(1).asm
字号:
ByteCnt DATA 28H ;I2C总线收发字节计数器
SlvAdr DATA 29H ;从器件地址(控制信息)
SubAdr DATA 2AH ;对于32Kbit(4BK)存储容量及以上器件来说,待读写
;单元地址为两字节,分别存放SubAdr、SubAdr+1单元中
RcvDat DATA 30H ;接收数据缓冲区(长度为8字节)
XmtDat DATA 48H ;发送数据缓冲区(长度为8字节)
FHbit BIT 00H ;发送及接收成功标志存放在00H位单元中。0表示成功;
;1表示失败
NOACK BIT 01H ;读操作时主器件非应答标志位,1表示非应答,0表示应答。
SCL BIT P1.0 ;模拟I2C总线时钟信号, 输出
SDA BIT P1.1 ;模拟I2C总线数据/地址引脚,双向
ORG 0000H
LJMP MAIN ;跳转主程序入口地址
ORG 0100H
PROC MAIN ;主程序
MAIN:
MOV SP, #0DFH ;对于具有256字节内部RAM芯片来说,
;将0E0H-0FFH,共计32字节作为堆栈区
MOV DPTR, #8000H ;关闭蜂鸣器
MOV A, #0FFH
MOVX @DPTR, A
;---复位后,将08H-0FF内部RAM单元清0。
MOV R7, #248
MOV R0, #08H
LOOPIC1:
MOV @R0, #0
INC R0
DJNZ R7, LOOPIC1
;读24C01的7E、7FH单元
MOV ByteCnt, #2 ;传送2字节
MOV SlvAdr, #0A0H ;24C01 EEPROM从器件地址
MOV SubAdr, #7EH ;从7EH单元开始
LCALL ReceData ;调用读EEPROM子程序,读出的2个字节存放在30-31单元中.
;判别读出的内容
MOV R0, #RcvDat
MOV A, @R0
CJNE A, #5AH, NEXT1
INC R0
MOV A, @R0
CJNE A, #0A5H, NEXT1
;等于5A、0A5H,说明已经初始化过,把日历时钟读到48-4EH单元中
MOV ByteCnt, #7 ;传送7字节
MOV SlvAdr, #0A2H ;日历时钟器件地址为A2H
MOV SubAdr, #02H ;从日历时钟的02H单元开始
LCALL ReceData ;调用读EEPROM子程序,读出的7个字节存放在30-36单元中.
SJMP NEXT2
NEXT1:
;日历初始化
MOV R0, #XmtDat ;发送缓冲区首地址送R0
MOV @R0, #00H ;秒初值
INC R0
MOV @R0, #30H ;分初值
INC R0
MOV @R0, #12H ;时初值
INC R0
MOV @R0, #09H ;日初值
INC R0
MOV @R0, #03H ;星期初值
INC R0
MOV @R0, #11H ;世纪及月初值
INC R0
MOV @R0, #04H ;年初值
MOV ByteCnt, #07H ;传送7字节
MOV SlvAdr, #0A2H ;PCF8563日历时钟器件地址为A2H
MOV SubAdr, #02H ;从日历时钟的02H单元开始
LCALL SendData ;调用写EEPROM多字节写入过程,将发送缓冲区内的信息写入
;PCF8563日历芯片内日历时间单元
;把初始化标志写入EEPROM的24C01芯片的7EH、7FH单元中。
MOV R0, #XmtDat ;发送缓冲区首地址送R0
MOV @R0, #5AH
INC R0
MOV @R0, #0A5H
MOV ByteCnt, #02H ;传送2字节
MOV SlvAdr, #0A0H ;24C01 EEPROM从器件地址
MOV SubAdr, #7EH ;从7EH单元开始
LCALL SendData ;调用写EEPROM多字节写入过程,将发送缓冲区内的信息写入
;EEPROM的7EH、7FH单元中。
NEXT2:
SJMP $ ;虚拟主程序
END
;------------------------串行EEPROM、日历时钟读写子程序------------
; 发送数据子程序
;名称:SendData
;描述:发送ByteCnt 个字节给从器件,如I2C总线串行EEPROM
;从器件地址在SlvAdr 中,存储单元地址在SubAdr 中
;所发送数据的字节数在ByteCnt中,发送的数据在XmtDat 缓冲区中
;成功发送数据,FHbit标志为0; 当FHbit为1时表示从器件无应答或损坏
;*************************************************************************************************
Proc SendData
SendData:
PUSH PSW
PUSH ACC
CLR RS0 ;使用2区(10)
SETB RS1
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,SenReturn ;从器件不应答返回
;--------对于存储器单元地址为16位的EEPROM存储器
; MOV R0, #SubAdr+1
; MOV A, @R0 ;存储单元地址高8位送累加器Acc,即先发送高8位地址A15~A8
; LCALL SentByte ;发存储单元地址
; JB FHbit,SenReturn ;从器件不应答返回
;--------对于存储单元地址为8位时,仅保留如下内容即可
MOV R0, #SubAdr
MOV A, @R0 ;存储单元地址低8位送累加器Acc,再发送低8位地址A7~A0
LCALL SentByte ;发存储单元地址
JB FHbit,SenReturn ;从器件不应答返回
MOV R0,#XmtDat ;取发送数据缓冲区首址
SentNext:
MOV A,@R0
LCALL SentByte ;发送一次数据
JB FHbit,SenReturn ;出错返回
INC R0 ;取下一个数据
DJNZ ByteCnt,SentNext ;重复操作直到发送完最后一个数据
LCALL STOP ;停止IC总线操作
;********查询方式检测内部写入周期是否已完成**********
LOOP:
NOP ;两次操作之间的延迟
NOP
NOP
NOP
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,LOOP ;从器件不应答返回
LCALL STOP ;停止IC总线操作
;***********************************************************
SenReturn:
POP ACC
POP PSW
RET
END
;************************************************************************************************
; 接收数据子程序
;名称:ReceData
;描述:自从器件(如I2C总线串行EEPROM)读出ByteCnt个字节数据信息
;从器件地址在SlvAdr 中,待读出的存储单元地址在SubAdr 中
;所发送数据的字节数在ByteCnt中,接收的数据放在RevDat 缓冲区中
;成功接收数据,FHbit标志为0; 当FHbit为1时表示从器件无应答或损坏
;*************************************************************************************************
PROC ReceData
ReceData:
PUSH PSW
PUSH ACC
CLR RS0 ;使用2区(10)
SETB RS1
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,RevReturn ;从器件不应答返回
;-----------对于存储器单元地址为16位的EEPROM存储器
; MOV R0, #SubAdr+1
; MOV A, @R0 ;存储单元地址高8位送累加器Acc,即先发送高8位地址A15~A8
; LCALL SentByte ;发存储单元地址
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -