这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» 请教单片机模拟I2C总线来读写AT24C02存储器的问题

共7条 1/1 1 跳转至

请教单片机模拟I2C总线来读写AT24C02存储器的问题

工程师
2021-11-01 21:22:21 打赏

大家好,谁有时间帮我解答一下这个问题,我写了一个iic的小程序,可为什仿真时iic监视器显示有数据,而芯片AT24C02C的存储器里显示的全是FF,我程序在18号地址写的是20,是程序软件的问题吗?

#include

#include

#define uchar unsigned char

#define ui unsigned int

sbit sda=P2^1;

sbit scl=P2^0;

uchar c=20;

void delay7us() // 延时函数

{

unsigned char a;

for(a=2;a>0;a--);

}

void init()

{sda=1;

delay7us();

scl=1;

delay7us();

}

/*启动信号函数*/

void start() //启动信号函数

{ scl=1;

sda=1;

delay7us();

sda=0;

delay7us();

}

/*写一个字节的函数*/

void write_iic_byte(uchar dat)

{ uchar i;

scl=0; /*主机拉低为的是SDA数据线

可以发生变化并为SDA拉高,让

接受设备接收数据做准备*/

/*发送八位数据*/

for(i=0;i<8;i++)

{ if(dat&0X80)

sda=1;/*主机将数据1存入SDA*/

else

sda=0;/*主机将数据0存入SDA

,也可认为是存入一个

存储器*/

scl=1; /*主机将时钟数据线拉高*/

delay7us(); /*延时接收设备在此期间

自动取走*/

dat=dat<<1;/* 数据左移一位,次高位

变成发送数据位*/

scl=0;/*时钟线拉低为更改发送数据

位做准备,只有其为低数据线

上的数据才会发生改变。*/

}

sda=1;/*释放数据线*/

}

/*读一个字节的函数*/

uchar read_iic_byte()

{ uchar i,v;/*暂时为空变量,8次后

存储要保存的数据*/

sda=1;/*主机释放数据线,这数据

状态以后有发送设备决定*/

scl=0;/*主机将时钟信号线拉低,

/*SDA线上的数据才会改变*/

/*从设备发送八位数据*/

for(i=0;i<8;i++)

{ v=v<<1; /*第一次循环无意义,以后

发送用*/

scl=1; /*以后发送期间数据稳定*/

delay7us();/*延时使主机有时间取走

数据*/

if(sda) /*SDA发送从设备里最高位数据

1,第一次循环从此发送第一

位数据*/

v=v|0X01;/*把1传入变量V的最低位*/

scl=0; /*时钟线拉低发送数据由发送

设备自动改变*/


delay7us();/*延时使时钟线可靠拉低

,有充足时间数据被读走

*/

}

return v; /*被读的数据存在V中,

作为返回值/*返回*/

}

void stop()//停止信号函数

{scl=1;

sda=0;

delay7us();

sda=1;

delay7us();

}

/*产生和检测应答信号 */

uchar ack()

{uchar i;

scl=0;

sda=0;

delay7us();

scl=1;

delay7us();

while(sda==1)

{ i++;

if(i>260)

{

stop();

return 1;

}

}

return 0;

}

/* 产生非应答信号*/

void noack()

{scl=0;

sda=1;

delay7us();

scl=1;

delay7us();

scl=0;

}

void main()

{

{init();

start();

write_iic_byte(0XA0);

ack();

write_iic_byte(0X18);

ack();

write_iic_byte(c);

ack();

stop();

delay7us();

}

while(1);

}






关键词: AT24C02 存储器 I2C IIC

工程师
2021-11-01 21:41:22 打赏
2楼

我一般都是延时5US,不知道楼主你的7US会不会影响? 手册上是4.7和4US


工程师
2021-11-01 21:45:12 打赏
3楼

你的应答是错误的,SDA=1才是对的,这叫释放SDA端口
SDA=0了就无法检测电平状态了
有电脑,有开发板,不是复杂运算,仿真没有用,仿真要用在真正需要的地方IIC写入字节是可以很简单的,不需要那么复杂

void Write_Byte(unsigned char Byte) //写入器件的应答信号由从机给出
{
unsigned char i;
unsigned int k;
SCL=0;
Delay();
for(i=0;i<8;i++)
{
if(Byte&0x80)SDA=1;
else SDA=0;
Delay();
SCL=1;
Delay();
SCL=0;
Byte<<=1;
}
SCL=1; //给出一个上升沿,用于产生应答信号
Delay();
SDA=1;
while((SDA==1)&(k<1000)) //超时就不再等待应答
{
k++;
Delay();
} //等待SDA出现低电平,出现低电平就表示器件已经应答
SCL=0;
}


工程师
2021-11-01 21:50:21 打赏
4楼
向I2C总线写入一个字节时,在FOR循环中,每次左移一位,将SCL设置为高电平,必须延迟7微秒,然后将SCL拉低。 并重复下一个数位。



院士
2021-11-01 22:18:57 打赏
5楼

各位朋友的回复及楼主写的程序,一并学习了,谢谢大家。


专家
2021-11-05 12:51:07 打赏
6楼

学习了


专家
2021-11-05 13:04:49 打赏
7楼

学习了


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]