使用Proteus来进行89C52与24C02的I2C通讯仿真,实现将写入24C02的数据读出来点亮由P1控制的LED灯;
写数据后,应答信号SDA波形如图;仿真图如图。
目前问题是在proteus里面LED灯不能正常按照写入的数据来点亮,而下载到开发板却是正常的。
有如下疑问:
① 根据图示应答波形发现,SDA在SCL的下降沿期间发生了变化(拉高),这个是否正常?按照I2C应答时序图,应该是SCL拉低后一段时间SDA才能发生变化。看波形应该是24c02正常产生了应答,但是在SCL拉低时,SDA提早被释放了。
② 调试代码,将如下应答信号内的 while((sda==1)&&(i<250))i++; 这段延时给注释掉后,仿真可以正常点亮LED灯(但应答波形依旧),请问这段代码为什么会导致异常?
感谢!
void respons() //应答
{
uchar i;
scl=1;
delay();
// while((sda==1)&&(i<250))i++; // 注释掉此行代码后正常。
scl=0;
delay();
}
完整IIC代码:
***************************************************
#include<reg52.h>
#define uchar unsigned char
sbit sda=P2^0;
sbit scl=P2^1;
uchar a;
void delay()
{ ;; }
void start() //开始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
scl=0;
delay();
}
void stop() //停止
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
// scl=0;
// delay();
}
void respons() //应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++;
scl=0;
delay();
}
//void Send_respons() //发送应答信号,即给从机发0,如果不应答要发1,主程序中就不加这段程
序即可。
//{
// sda=0;
// delay();
// scl=1;
// delay();
// scl=0;
// delay();
//}
void init()
{
sda=1;
delay();
scl=1;
delay();
}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
delay();
sda=CY;
delay();
scl=1;
delay();
scl=0;
}
delay();
sda=1;
delay();
}
uchar read_byte()
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return k;
}
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
void write_add(uchar address,uchar date)
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address)
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
delay1(100);
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
void main()
{
init();
write_add(23,0xaa);
delay1(100);
P1=read_add(23);
while(1);
}