EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设备上擦除已有信息,重新编程。一般用在即插即用。
EEPROM模块在“蓝桥杯”单片机设计与开发项目比赛中经常出现,其在决赛中必然出现,在近四年中省赛出现过一次。可以说EEPROM的掌握是准备“蓝桥杯”单片机设计与开发比赛避不开的内容。
蓝桥杯单片机开发所使用的EEPROM储存芯片是AT24C02,通过IIC数据总线进行数据传输。通过一根SCL时钟信号线和SDA数据信号线串行传输。
引脚说明:
A0,A1,A2:硬件地址引脚。
WP:写保护引脚,接高电平只读,接地允许读和写。
SCL和SDA:IIC总线。
先把EEPROM和IIC的模块代码放出来
IIC.c
#include "reg52.h"
#include "intrins.h"
#include "I2C.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
void operate_delay(unsigned char t)
{
unsigned i;
while(t--)
for(i=0;i<112;i++);
}
void write_eeprom(unsigned char add,unsigned char val)
{
IIC_Start();
IIC_SendByte(0xA0);//器件地址
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(val);
IIC_WaitAck();
IIC_Stop();
operate_delay(10);
}
unsigned char read_eeprom(unsigned char add)
{
unsigned char da;
IIC_Start();
IIC_SendByte(0xA0);//器件地址
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xA1);//读取地址
IIC_WaitAck();
da = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return da;
}
代码中涉及到IIC通信协议的都会在比赛时由官方提供,我们也不是主要讲IIC通信协议的。这里就讲讲利用IIC与AT24C02通信的两个函数加一个操作延时函数。
void operate_delay(unsigned char t)
{
unsigned i;
while(t--)
for(i=0;i<112;i++);
}
这里首先重点提一下,AT24C02对时序要求较高,如果操作延时函数未延时到足够的时间,可能会导致写入失败或部分写入的情况。
EEPROM写数据
操作时序:
启动总线-----发送设备地址+写-----等待应答-----发送数据的储存地址(0x00-0xFF,256个字节)-----等待应答-----发送数据-----等待应答-----停止总线
注意:
在写数据的过程中,每成功写入一个字节,E2PROM存储空间的地址就会自动加1,当加到0xFF后,再写一个字节,地址就会溢出又变成0x00。
写数据的时候需要注意,E2PROM是先写到缓冲区,然后再“搬运到”到掉电非易失区。所以这个过程需要一定的时间,AT24C02这个过程是不超过5ms!如果在这个时候去让它应答是没有响应的!
所以,当我们在写多个字节时,写入一个字节之后,再写入下一个字节之前,必须等待E2PROM再次相应才可以。
但是当我们单字节写数据时,不用考虑得不到应答的问题,直接停止总线即可。
void write_eeprom(unsigned char add,unsigned char val)
{
IIC_Start();
IIC_SendByte(0xA0);//器件地址
IIC_WaitAck();
IIC_SendByte(add);//写入地址
IIC_WaitAck();
IIC_SendByte(val);//写入值
IIC_WaitAck();
IIC_Stop();
operate_delay(10);
}
EEPROM读数据
操作时序:
启动总线——发送设备地址——等待应答——发送数据储存地址+写——等待应答——发送设备地址+读——等待应答——读取数据——主机发送是否应答。
注意:
读取数据时一定要要等待应答
unsigned char read_eeprom(unsigned char add)
{
unsigned char da;
IIC_Start();
IIC_SendByte(0xA0);//器件地址
IIC_WaitAck();
IIC_SendByte(add);//写入地址
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xA1);//读取地址
IIC_WaitAck();
da = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return da;
}