📄 实验十一(1).asm
字号:
; JB FHbit,RevReturn ;从器件不应答返回
;-----------对于存储单元地址为8位时,仅保留如下内容即可
MOV R0, #SubAdr
MOV A, @R0 ;存储单元地址低8位送累加器Acc,再发送低8位地址A7~A0
LCALL SentByte ;发存储单元地址(只完成存储单元定位功能
;既不给数据,也没有给停止信号,因为停止总线后写操作
;才被执行,故称为“哑写”
JB FHbit,RevReturn ;从器件不应答返回
;*****完成“哑写”过程,将从器件地址计数器定位到将要读出的存储单元****
LCALL START ;重新启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
SETB ACC.0 ;将从器件地址改为读状态
LCALL SentByte ;发送从器件总线地址
JB FHBIT,RevReturn ;从器件不应答返回
;****准备接收数据*****************************************
CLR NOACK ;清除非应答标志
MOV R0,#Rcvdat ;取接收数据缓冲区首地址
DJNZ ByteCnt,Next ;继续接受下一字节
SJMP ReceLast ;减1为0,说明仅接收一个字节数据(也是最后一个字节)。
Next:
LCALL ReceByte ;接收一个字节数据
MOV @R0,A ;把接收到的数据放入接收缓冲区内。
INC R0 ;将指针移到缓冲区下一存储单元
DJNZ ByteCnt,Next ;重复进行直到最后一个字节
ReceLast:
SETB NOACK ;已接收了最后一个字节,主器件无需应答
LCALL ReceByte ;接收一个字节数据
MOV @R0,A ;把接收到的数据放入接收缓冲区内
LCALL STOP ;停止总线操作
RevReturn:
POP ACC
POP PSW
RET
END
;字节发送(写入)子程序
;用于将从器件地址字节或数据字节发送到从器件(串行EEPROM)中
;入口参数:发送字节信息存放在寄存器A中
;出口参数:返回标志存放在Fhbit(位地址)中
;0—成功;1—失败(从器件不应答,发送失败)
PROC SentByte
SentByte:
CLR FHbit ;清除失败标志。
MOV R7,#08H ;初始化发送数据位长度R7
SentLOOP:
CLR SCL ;主器件输出时,在SCL下降沿后立即输出数据,以便接收
;方(从器件)接收
RLC A ;将Acc.7位移到进位标志C中,即先写高位。
MOV SDA, C ;将数据位发送到SDA引脚。由于写入时用SCL上升沿同
;步,因此要先送数据后将SCL置高电平。
NOP ;SCL同步时钟低电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~6条空操作指令
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟3个NOP
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟7个NOP
SETB SCL ;使时钟引脚为高电平。
NOP ;SCL同步时钟高电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~8条空操作指令
; NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟3个NOP
; NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟6个NOP
DJNZ R7, SentLOOP ;R7减1不为0,则继续
CLR SCL ;当R7=0,则表示已发送Acc.0位,将SCL置低电平
;形成发送Acc.0位的时钟脉冲
NOP ;SCL同步时钟低电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~6条空操作指令
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟3个NOP
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟7个NOP
SETB SDA ;将与SDA引脚相连的I/O引脚锁存器位置1,以便将SDA
;引脚能作输入引脚,以便检测从器件回送的应答信
;号(这一指令不能少,否则当发送的Acc.0位为0时,
;I/O引脚锁存器为0,结果输入信号总被钳位在低电
;平)
SETB SCL ;输出应答信号检测脉冲头
NOP ;延迟两个机器周期后,再读接收方回送的应答信号
NOP
JNB SDA, SeACK ;如果SDA为低电平,则表示收到应答信号
SETB FHbit ;否则将FHbit置1,表示发送失败
SeACK:
NOP
NOP
NOP ;注:完成字节写入后,SDA引脚锁存器已经为1
CLR SCL ;将SCL引脚置为低电平,结束应答检测脉冲
RET
END
;字节接收子程序。
;用于接收从器件(串行EEPROM)发送来的存储单元信息。
;入口参数:发送字节信息存放在寄存器A中
;出口参数:
; 接收到的数据信息存放在Acc中
; 返回标志存放在Fhbit(位地址)中
; 0—成功;1—失败(从器件不应答,发送失败)
PROC ReceByte
ReceByte:
SETB SDA
;在单字节(立即读或选择性读)读程序中,接收总是发生在写入从器件地址后
;为了能检测从器件回送的低电平应答信号,SDA已被置为输入状态,在接收子
;程序中,可以省去“SETB SDA”指令
;但在连续读程序中,主器件每收到一个字节的数据后,向从器件发送一个低
;电平的应答信号,这时SDA引脚对应的I/O锁存器出于输出状态,且I/O锁存器为0
;不能省去该指令。
MOV R7,#08H ;初始化接收数据位长度R7
ReceLOOP:
CLR SCL
NOP ;SCL同步时钟低电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~8条空操作指令
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟4个NOP
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟8个NOP
NOP
SETB SCL ;形成SCL上升沿
MOV C,SDA ;在SCL上升沿后,无需延迟,可立即读输入数据
RLC A
NOP ;SCL同步时钟高电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~8条空操作指令
; NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟2个NOP
; NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟5个NOP
DJNZ R7,ReceLOOP
CLR SCL ;当R7=0,则表示已接收到Acc.7位,将SCL置低电平,
;形成接收Acc.7位的时钟脉冲
JNB NOACK,SNOACK ;如果非应答标志NOACK为0,需给出应答信号
CLR NOACK ;清除非应答标志。
SETB SDA ;非应答标志有效(为1),输出高电平的非应答信号。
SJMP NEXT
SNOACK:
CLR SDA ;主器件未读出所有指定字节,输出低电平应答信号。
NOP
NEXT:
NOP
NOP
SETB SCL ;将SCL置为高电平,输出第9个SCL同步脉冲
NOP ;以便发送方检测接收方(主设备)输出的应答信号
NOP ;SCL同步时钟高电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~8条空操作指令
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟2个NOP
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟5个NOP
CLR SCL ;将SCL置为低电平,以便接受数据或发送停止信号。
RET
END
;“启动”I2C总线串行EEPROM子程序
START:
SETB SCL ;由于空闲时,SCL、SDA为高电平
CLR SDA ;在SCL为高电平时,使SDA由高电平变为低电平,启动I2C总线。
NOP ;SDA下降沿到SCL下降沿时间必须大于启动信号的保持时间(4.0us)
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟5个器件周期
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟9个机器周期
NOP
; NOP
CLR SCL ;将SCL时钟置为低电平,以便发送或接收数据。
RET
;“停止”I2C总线串行EEPROM子程序
STOP:
CLR SDA ;由于完成字节发送时,SDA引脚锁存器为1(目的是为了检测
NOP ;从器件回送的应答信号;而在读操作结束时,也通过SDA引脚
NOP ;输出了高电平的应答信号,因此执行停止总线操作时,
;CLR SDA指令不能少!
SETB SCL
NOP ;SCL上升沿到SDA上升沿时间必须大于停止信号的建立时间(4.0us)
NOP ;当晶振频率为12MHz时,对于12时钟来说,需要延迟5个器件周期
NOP ;当晶振频率为12MHz时,对于6时钟来说,需要延迟9个机器周期
NOP
; NOP
SETB SDA ;在SCL为高电平时,使SDA由低电平变为高电平,停止I2C总线。
RET
;“停止”总线操作结束后,SCL、SDA均处于高电平状态,即总线处于空闲状态。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -