AT24C02介绍
AT24C01/02/04/08/16…是一个 1K/2K/4K/8K/16K 位串行 CMOS,内部含有128/256/512/1024/2048 个 8 位字节,AT24C01 有一个 8 字节页写缓冲器,AT24C02/04/08/16 有一个 16 字节页写缓冲器。该器件通过 I2C 总线接口进行操作,它有一个专门的写保护功能。51开发板上使用的是 AT24C02(EEPROM)芯片,此芯片具有 I2C 通信接口,芯片内保存的数据在掉电情况下都不丢失,所以通常用于存放一些比较重要的数据等。AT24C02 芯片管脚及外观图如下图所示:
芯片管脚使用说明
引脚号 | 引脚名称 | 功能说明 | |
---|---|---|---|
1 | A0 | 地址输入。A2、A1和A0是器件地址输入引脚。 24C02/32/64使用A2、A1和A0输入引脚作为硬件地址,总线上可同时级联8个24C02/32/64器件。 24C08使用A2输入引脚作为硬件地址,总线上可同时级联2个24C08器件,AO和A1为空脚,可接地。 24C04使用A2和A1输入引脚作为硬件地址,总线上可同时级联4个24C04器件,A0为空脚,可接地。 24C16未使用器件地址引脚,总线上最多只可连接一个16K器件,A2、A1和A0为空脚,可接地。 | |
2 | A1 | ||
3 | A2 | ||
5 | SDA | 串行地址和数据输入/输出。SDA是双向串行数据传输引脚,极开路,需外接上拉电阻到Vcc(典型值10kQ)。 | |
6 | SCl | 串行时钟输入。SCL同步数据传输,上升沿数据写入,下降沿数据读出。 | |
7 | WP | 写保护。WP引脚提供硬件数据保护。当WP接地时,允许数据正常读写操作:当WVP接Vcc时,写保护,只读。 | |
4 | GND | 地 | |
9 | VCC | 正电源 |
AT24C02 器件地址为 7 位,高 4 位固定为 1010,低 3 位由 A0/A1/A2 信号线的电平决定。 因为传输地址或数据是以字节为单位传送的,当传送地址时,器件地址占 7 位,还有最后一位(最低位 R/W)用来选择读写方向,它与地址无关。其格式如下
51开发板已经将芯片的 A0/A1/A2 连接到 GND,所以器件地址为1010000,即 0x50(未计算最低位)。如果要对芯片进行写操作时,R/W 即为 0,写器件地址即为 0XA0;如果要对芯片进行读操作时,R/W 即为 1,此时读器件地址为 0XA1。开发板上也将 WP 引脚直接接在 GND 上,此时芯片允许数据正常读写。
芯片的 SCL 和 SDA 管脚是连接在单片机的 P2.1 和 P2.0 上,为了让 IIC 总线默认为高电平,通常会在 IIC总线上接上拉电阻,在图中并没有看到 SCL 和 SDA 管脚有上拉电阻,这是因为51开发板单片机 IO 都外接了 10K 上拉电阻,当单片机 IO 口连接到芯片的 SCL 和 SDA脚时即相当于它们外接上拉电阻,所以此处可以省去。
实验
下面是使用IIC控制AT24C02代码,按键P3_1、P3_0、P3_2、P3_3来控制输入的内容。
当案件P3_2按下值会自增1,当案件P3_3按下值会归零。P3_1按下会将数据写到AT24C02中,当P3_0按下会读出AT24C02的值。public是一个延时函数,这个不再展示
main.c
#include <REGX52.H>
#include "public.h"
#include "at24c02.h"
#include "key.h"
#include "smg.h"
void main()
{
u8 key=0;
u8 val=0;
u8 dis[3];
while(1)
{
key=key_scan(0);
if(key==KEY1_PRESS) at24c02_write_byte(0,val);
else if(key==KEY2_PRESS) val=at24c02_read_byte(0);
else if(key==KEY3_PRESS) val++;
else if(key==KEY4_PRESS) val=0;
dis[0]=val/100;
dis[1]=val%100/10;
dis[2]=val%100%10;
smg_display(dis,6);
}
}
IIC.c
#include "IIC.h"
void IIC_Start()
{
IIC_SDA=1;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SDA=0;
delay_10us(1);
IIC_SCL=0;
delay_10us(1);
}
void IIC_Stop()
{
IIC_SDA=0;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SDA=1;
delay_10us(1);
}
void IIC_Ack()
{
IIC_SCL=0;
IIC_SDA=0;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
void IIC_Nack()
{
IIC_SCL=0;
IIC_SDA=1;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
u8 IIC_Wait_Ack()
{
u8 time=100;
IIC_SCL=1;
delay_10us(1);
while(IIC_SDA)
{
time--;
if(time==1)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}
void IIC_Write_Byte(u8 dat)
{
u8 i=0;
IIC_SCL=0;
for(i=0;i<8;i++)
{
if((dat & 0x80)>0) IIC_SDA=1;
else IIC_SDA=0;
dat<<=1;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
delay_10us(1);
}
}
u8 IIC_Read_Byte(u8 ack)
{
u8 i=0,dat=0;
for(i=0;i<8;i++)
{
IIC_SCL=0;
delay_10us(1);
IIC_SCL=1;
dat<<=1;
if(IIC_SDA) dat++;
delay_10us(1);
}
if(!ack) IIC_Nack();
else IIC_Ack();
return dat;
}
IIC.h
#ifndef __IIC_H_
#define __IIC_H_
#include "public.h"
sbit IIC_SDA=P2^0;
sbit IIC_SCL=P2^1;
void IIC_Start();
void IIC_Stop();
void IIC_Ack();
void IIC_Nack();
u8 IIC_Wait_Ack();
void IIC_Write_Byte(u8 dat);
u8 IIC_Read_Byte(u8 ack);
#endif
at24c02.c
#include "at24c02.h"
#include "IIC.h"
void at24c02_write_byte(u8 addr ,u8 dat)
{
IIC_Start();
IIC_Write_Byte(0xA0);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
IIC_Write_Byte(dat);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(10);
}
u8 at24c02_read_byte(u8 addr)
{
u8 res=0;
IIC_Start();
IIC_Write_Byte(0xA0);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Write_Byte(0xA1);
IIC_Wait_Ack();
res=IIC_Read_Byte(0);
IIC_Stop();
return res;
}
at24c02.h
#ifndef __AT24C02_H_
#define __AT24C02_H_
#include "public.h"
void at24c02_write_byte(u8 addr ,u8 dat);
u8 at24c02_read_byte(u8 addr);
#endif
smg.c
#include "smg.h"
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void smg_display(u8 dat[],u8 pos)
{
u8 i=0;
u8 pos_temp=pos-1;
for(i=pos_temp;i<8;i++)
{
switch(i)
{
case 0: LSC=1;LSB=1;LSA=1;break;
case 1: LSC=1;LSB=1;LSA=0;break;
case 2: LSC=1;LSB=0;LSA=1;break;
case 3: LSC=1;LSB=0;LSA=0;break;
case 4: LSC=0;LSB=1;LSA=1;break;
case 5: LSC=0;LSB=1;LSA=0;break;
case 6: LSC=0;LSB=0;LSA=1;break;
case 7: LSC=0;LSB=0;LSA=0;break;
}
SMG_A_DP_PORT=gsmg_code[dat[i-pos_temp]];
delay_10us(100);
SMG_A_DP_PORT=0x00;//ÏûÒô
}
}
smg.h
#ifndef _smg_H
#define _smg_H
#include <REGX52.H>
#include "public.h"
#define SMG_A_DP_PORT P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
void smg_display(u8 dat[],u8 pos);
#endif
key.c
#include "key.h"
u8 key_scan(u8 mode)
{
static u8 key=1;
if(mode)key=1;
if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
{
delay_10us(1000);
key=0;
if(KEY1==0)
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEY3==0)
return KEY3_PRESS;
else if(KEY4==0)
return KEY4_PRESS;
}
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
{
key=1;
}
return KEY_UNPRESS;
}
key.h
#ifndef _key_H
#define _key_H
#include "public.h"
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
u8 key_scan(u8 mode);
#endif