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

📄 实验十一(1).asm

📁 单片机只是别人的东西
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;     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 + -