新闻中心

EEPW首页>嵌入式系统>设计应用> 用IIC总线读取E2PROM存储器数据

用IIC总线读取E2PROM存储器数据

作者: 时间:2016-11-24 来源:网络 收藏
简单介绍一下I2C总线原理:
IIC总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。
IIC总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 (记住这个就够了,其他都是废话!)
II C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

注意到IIC总线是需要接上拉电阻的!因为连到IIC总线的器件的输出基本为开漏输出.

起始和终止信号 :SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。下图一目了然。


数据传送格式(1)字节传送与应答
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。
对数据时进行位操作,即来一个SCL始终高电平就写入或者读出一位数据,这个一定要清楚!


下面介绍ATMEL公司的串行E2PROM产品——AT24C系列
AT24C01:128字节(128×8位);
AT24C02:256字节(256×8位);
AT24C04:512字节(512×8位)AT24C08:1K字节(1K×8位);
AT24C16:2K字节(2K×8位);

本次实验用的是AT24C02,所以存储器的地址有256字节(在IIC总线寻址中读取存储器首地址时首地址的范围为0~256,因为AT24C02的容量为256字节)

下面是AT24C02的电路图,注意到SDA和SCL均有连接10K的上拉电阻,本实验中SDA接89C52的P2.0口,SCL接89C52的P2.1口。

AT24C02的芯片地址如下图,1010为固定,A0,A1,A2正好与芯片的1,2,3引角对应,为当前电路中的地址选择线,三根线可选择8个芯片同时连接在电路中,当要与哪个芯片通信时传送相应的地址即可与该芯片建立连接,TX-1B实验板上三根地址线都为0。最后一位R/W为告诉从机下一字节数据是要读还是写,0为写入,1为读出。


AT24C02的芯片地址(0xa0为写,0xa1为读)

任意地址写入数据和任意地址读取数据分别如下图所示
读取数据:


注意,读数据的时候也要先进行写操作,目的是写入器件地址以寻找合适的器件,当器件与地址匹配时,器件会发出一个应答信号,这样就可以让单片机确定该读哪个器件,这样就可以开始读取数据了.
写入数据:



下面是程序:
#include
#define uchar unsigned char
sbit sda=P2^0;
sbit scl=P2^1;
uchar a;
void delay() //延时2us
{ ;; }
void start() //开始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop() //停止
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void respons() //应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++;
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;
scl=0;
delay();
sda=CY;
delay();
scl=1;
delay();
// scl=0;
// 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; //一次读一位,从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();
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);
}


评论


技术专区

关闭