89c51 IIC模拟串行通信问题
各位用过89c51 IIC模拟通信的朋友,以下的程序为写串行E2PROM子程序,但是仿真时第10、11行程序
ACALL SENDBYTE ;出错
DJNZ R7,AGAIN;出错
请问大家应该怎样解决此问题,比如在IIC模拟协议方面,整个程序还有其它错误吗?我看了一些程序,
他们用NOP进行延时,这样以延时子程序有何差别
;写串行E2PROM子程序EEPW
; A0H=10100000(命令1010+器件3位地址+读/写。 器件地址一个芯片,是000)
; (R4)=片内字节地址
; (R1)=欲写数据存放地址指针
; (R7)=连续写字节数n
SCL BIT P3.4 ;定义24C02的串行时钟线
SDA BIT P3.5 ;定义24C02的串行数据线
EEPW: MOV P1,#0FFH
ACALL START ;发开始信号
MOV A,#0A0H ;送器件地址
ACALL SENDBYTE
MOV A,R4 ;送片内字节地址
ACALL SUBS
AGAIN: MOV A,@R1
ACALL SENDBYTE ;调发送单字节子程序INC R1
DJNZ R7,AGAIN;连续写n个字节
;产生I2C总线数据传输停止信号
STOP: SETB SCL
CLR SDA
ACALL SOMENOP
SETB SDA
ACALL SOMENOP
RET
;产生I2C总线数据传输起始信号
START: SETB SDA ;置SDA为高电平状态
SETB SCL ;置SCL为高电平状态
ACALL SOMENOP ;模拟SCL高电平状态计数
CLR SDA ;使SDA产生一个由高到低的跳变
ACALL SOMENOP ;延时,模拟SDA低电平状态计数
CLR SCL ;将SCL置为低电平状态
RET
;SENDBYTE 向I2C总线发送一个字节
;ACC待发送的数据字节存放在ACC中
SENDBYTE: MOV COUNTER,#08H ;一个字节共送出8位数据
SENDBYTE1: CLR SCL ;置SCL为低电平状态
RLC A ;带进位循环左移,将最高位移至C
MOV SDA,C ;将当前数据位送到数据线SDA
ACALL SOMENOP ;计数SCL低电平状态周期数
SETB SCL ;置SCL为高电平状态
ACALL SOMENOP ;计数SCL高电平状态周期数
DJNZ COUNTER,SENDBYTE1 ;判断8个数据是否发送完成
CLR SCL ;字节发送完成,置SCL为低电平状态
;RET
;等待从机(或接收器)返回一个响应信号ACK(或新的开始数据传输信号)
WAITACK: CLR SCL ;置SCL为低电平
SETB SDA ;释放SDA信号线
ACALL SOMENOP ;延时,从机或接收器的响应信号\应该在这段延时期间出现
SETB SCL ;置SCL为高电平,准备判断SDA
ACALL SOMENOP ;延时
WAITACK1: MOV C,SDA
JC WAITACK ;SDA为低电平,返回了响应信号\否则等待新的开始数据传输信号
CLR SDA ;响应信号ACK或新的开始数据传输\信号出现,将SDA置为低电平状态
CLR SCL ;将SCL置为低电平状态
;RET
;向I2C总线发出一个响应信号ACK
ACK: CLR SDA ;在SCL为低电平期间改变SDA状态
ACALL SOMENOP ;置SDA为低电平
SETB SCL ;释放SCL信号线
ACALL SOMENOP ;延时
CLR SCL ;完成高电平状态计时,使SCL重新进入低电平状态
RET
;延时子程序
SOMENOP: MOV COUNTER1,#00H ;延时用计数器清零
SOMNOP1:
DJNZ COUNTER1,SOMNOP1 ;判断延时计数器是否结束
RET
END
[解决办法]
我有调试成功的IIC模拟程序,email:tl_mail@126.com