使用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);
}
咨询一个I2C总线通讯的应答信号异常问题

关键词: I2C IIC 通信

我前段时间正好做过I2C 方面的研究和学习,可以参考我下面的笔记
15 03 44 02 IIC读写 主从机信号时间关系.png
void IIC_Delay()
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
void IIC_Init()
{
P2M0&=0x3f;
P2M1&=0x3f;
SDA_GPIO=1;
SCL_GPIO=1;
}
void IIC_Start()//IIC启动信号
{
SDA_GPIO=1;
SCL_GPIO=1;
IIC_Delay();
SDA_GPIO=0;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}
void IIC_Stop()//IIC停止信号
{
SDA_GPIO=0;
SCL_GPIO=1;
SDA_GPIO=1;
IIC_Delay();
}
void IIC_Write_Byte(u8 IIC_Byte)//向总线发送一个字节
{
u8 i;
SCL_GPIO=0;
SDA_GPIO=1;
for(i=0;i<8;i++)
{
SDA_GPIO=(bit)(IIC_Byte&0x80);
IIC_Byte<<=1;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}
}
u8 IIC_Read_Byte()
{
u8 i,Value;
SCL_GPIO=0;
SDA_GPIO=1;
for(i=0;i<8;i++)
{
Value=(Value<<1)|SDA_GPIO;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}
return Value;
}
u8 IIC_Read_Ack()//单片机检测IIC从机发来的应答信号
{
u8 ack=1,i=0;
SCL_GPIO=1;
IIC_Delay();
while((ack)&&(i<5))
{
ack=SDA_GPIO;
i++;
}
SCL_GPIO=0;
return ack;
}
void IIC_Write_Ack(bit ack)//单片机发送应答给从机
{
SDA_GPIO=ack;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
SDA_GPIO=1;
IIC_Delay();
}
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
Buck电路工作在CCM模式下电感电流的计算公式是什么?被打赏5分 | |
buck电路工作原理被打赏5分 | |
基于MSPM0L1306的MODBUS-RTU协议通讯实验被打赏100分 | |
我想要一部加热台+多合一调试工具被打赏18分 | |
每周了解几个硬件知识+485硬件知识分享被打赏10分 | |
【换取手持数字示波器】树莓派PICO调试器官方固件本地化部署实践被打赏24分 | |
【换取手持数字示波器】分享一个KEIL无法识别CMSIS-DAP调试器的解决办法被打赏20分 | |
【换取手持数字示波器】分享一个自制的ArduinoNano扩展板底板被打赏23分 | |
【换取手持示波器】树莓派PICOW网页烟花被打赏18分 | |
【换取手持示波器】树莓派PICO逻辑分析仪被打赏16分 |