一. 芯片简介
AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节,采用先进CMOS技术实质上减少了器件的功耗。 AT24C02有一个8字节页写缓冲器,该器件通过IIC总线接口进行操作,有一个专门的写保护功能。
二. 芯片参数
1.特点
2.引脚定义
A0-A2引脚为芯片地址,用于多器件工作模式; SDA、SCL分别为IIC通信的数据线和时钟线; WP为写保护引脚,当该引脚接 GND 时,允许正常的读/写操作。 当该引脚接 VCC 时,芯片启动写保护功能;
3.参考电路
A0-A2接到GND上,地址固定为0; SCL、SDA引脚内部为开漏输出,所以需接上拉电阻; WP引脚接GND,表示芯片可读可写。
三. 通信接口
1.芯片读写地址
在进行I2C通信时,主机发送启动信号后,再发送寻址信号。 器件的地址有7位和10位,以7为地址寻址为例; 寻址信号由一个字节构成,高7位为地址位,最低位为方向位,用来表示主机与从器件的数据传输方向;
方向位0代表主机接下来对从器件进行写操作; 方向位为1,表明主机接下来对器件进行读操作。
如上图,AT24C02的高4位是固定的,为1010b,低3位则由A0/A1/A2信号线的电平决定。 按照我们此处的连接, A0/A1/A2 均为 0,所以 EEPROM 的 7 位设备地址是:1010 000b ,即 0x50。
由于 I2C 通讯时常常是地址跟读写方向连在一起构成一个 8 位数,且当R/W 位为 0 时,表示写方向,所以加上 7 位地址,其值为“ 0xA0”,常称该值为 I2C 设备的“写地址”; 当 R/W 位为 1 时,表示读方向,加上 7 位地址,其值为“ 0xA1”,常称该值为“读地址”。
A0/A1/A2输入脚用于多个器件级联时设置器件地址,当这些脚悬空时默认值为0。 当使用AT24C02 时最大可级联8个器件。 如果只有一个AT24C02被总线寻址,这三个地址输入脚(A0、A1、A2 )可悬空(接地也可以)或连接到Vss,如果只有一个AT24C01被总线寻址这三个地址输入脚(A0、A1、A2 )必须连接到Vss。
2.IIC通信
由于51单片机内部无集成IIC控制硬件资源,所以需要软件模拟IIC通信。 函数有四个,分别为IIC起始信号、IIC停止信号、IIC读取字节、IIC写入字节等函数。
/*********************IIC.h*************************************/
//--定义使用的IO口--//
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
//--声明全局变量--//
void I2C_Delay10us();
void I2C_Start(); //起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Stop(); //终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
uchar I2C_SendByte(uchar dat, uchar ack);//使用I2c读取一个字节
uchar I2C_ReadByte(); //通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,保持发送信号I2C_SDA保持稳定
/*********************IIC.c*************************************/
//延时:1us
void I2C_Delay10us()
{
uchar a, b;
for(b=1; b>0; b--)
{
for(a=2; a>0; a--);
}
}
// 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
I2C_SDA = 0;
I2C_Delay10us();//保持时间是>4us
I2C_SCL = 0;
I2C_Delay10us();
}
//终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
void I2C_Stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间大于4.7us
I2C_SDA = 1;
I2C_Delay10us();
}
//通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间, 保持发送信号I2C_SDA保持稳定
uchar I2C_SendByte(uchar dat, uchar ack)
{
uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0; a<8; a++)//要发送8位,从最高位开始
{
I2C_SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
dat = dat << 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间>4.7us
I2C_SCL = 0;
I2C_Delay10us();//时间大于4us
}
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
{
b++;
if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
}
I2C_SCL = 0;
I2C_Delay10us();
return 1;
}
// 使用I2c读取一个字节
uchar I2C_ReadByte()
{
uchar a = 0,dat = 0;
I2C_SDA = 1; //起始和发送一个字节之后I2C_SCL都是0
I2C_Delay10us();
for(a=0; a<8; a++)//接收8个字节
{
I2C_SCL = 1;
I2C_Delay10us();
dat <<= 1;
dat |= I2C_SDA;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
return dat;
}
四 .控制程序
实现了基本IIC通讯函数后,就可对AT24C02进行操作,主要是写入数据和读取数据两个函数。
芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00FF,共256个寻址单位。 所以可任意在00FF地址写入我们需要保存的数据。
1.AT24C02写入数据
时序顺序为: 发送开始信号,IIC启动->发送器件地址,其中读写标志位为写->发送器件内部存储地址->向器件中写入数据->发送停止信号,IIC停止;
//函数功能 : 往24c02的一个地址写入一个数据
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2C_Start();
I2C_SendByte(0xa0, 1);//发送写器件地址
I2C_SendByte(addr, 1);//发送要写入内存地址
I2C_SendByte(dat, 0); //发送数据
I2C_Stop();
}
2.AT24C02读取数据
时序顺序为: 发送开始信号,IIC启动->发送器件地址,其中读写标志位为写->发送器件内部->发送开始信号,IIC再次启动->发送器件地址,其中读写标志位为读->从器件读出数据->返回所读取的数据;
// 函数功能 :读取24c02的一个地址的一个数据
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2C_Start();
I2C_SendByte(0xa0, 1); //发送写器件地址
I2C_SendByte(addr, 1); //发送要读取的地址
I2C_Start();
I2C_SendByte(0xa1, 1); //发送读器件地址
num=I2C_ReadByte(); //读取数据
I2C_Stop();
return num;
}
3.AT24C02读写数据
实现以上的读写功能,就可以使用AT24C02来实现我们需要的功能。 功能为:使用按键1,写入num0; 按键2,读取num0; 按键3,使num0加1; 按键4,清零num0;
void main()
{
unsigned int num0 = 0,num1 = 0,num2 = 0,n;
LcdInit();
while(1)
{
if(K1 == 0) //按键1按下,将num0写入eeprom
{
Delay10ms(1);
if(K1 == 0)
{At24c02Write(2,num0);
At24c02Write(3,num0);}
while((n < 20)&&(K3==0))
{
n++;
Delay10ms(1);
}
n=0;
n=0;
}
if(K2 == 0) //按键2按下,读取eeprom数据
{
Delay10ms(1);
if(K2 == 0)
{num1 = At24c02Read(2);
num2 = At24c02Read(3); }
while((n < 20)&&(K2 == 0))
{
n++;
Delay10ms(1);
}
n=0;
}
if(K3 == 0) //按键3按下,使num0自加1
{
Delay10ms(1);
if(K3 == 0)
num0++;
while((n < 50)&&(K3 == 0))
{
n++;
Delay10ms(1);
}
n=0;
if(num0==256)
num0=0;
}
if(K4 == 0) //按键4按下,清零
{
Delay10ms(1);
if(K4 == 0)
num0 = 0;
while((n < 50) && (K4 == 0))
{
n++;
Delay10ms(1);
}
n=0;
}
LCD_Display();
}
}
全部0条评论
快来发表一下你的评论吧 !