EEPROM

基础知识

电可擦除只读存储器,作用就是可以存储数据,板子断电之后数据不会丢失,板子再次上电,可以从里面读取数据。可以写一百万次,数据可以存100年,超级牛哔!

EEPROM有2k存储空间,可以存256个字节,可支持一次写入8个字节,一个内存地址可写入一个字节。

红框框出的就是EEPROM芯片和上拉电阻

电路原理

A0、A1、A3:代表器件地址,因为总线上可以挂载多个器件,所以IIC协议需要器件地址以区分。

WP:写入保护,当WP为高电平时,AT24C02无法写入数据,但是蓝桥杯板直接接到了GND,所以我们就不用管这个,可以进行任意读写。

读写EEPROM

EEPROM有很多种读写方式,但是只需要掌握以下两种就可以了

//写AT24C02
void vWrite_EEPROM(u8 add, u8 dat)
{
    IIC_Start();
    IIC_SendByte(0xa0);//AT24C02器件地址,因为蓝桥杯板上还挂载了AD-DA芯片,必须加以区分
                        //读写控制信号为低电平时为写,所以最低位是0
    IIC_WaitAck();
    IIC_SendByte(add);//写地址
    IIC_WaitAck();
    IIC_SendByte(dat);//写数据
    IIC_WaitAck();
    IIC_Stop();
    vDelay_Ms(5);//必须延时5ms,延长两次写的间隔,不然写入数据会出错,也可能损坏EEPROM
}

//读AT24C02
u8 ucRead_EEPROM(u8 add)
{
    u8 dat;
    IIC_Start();
    IIC_SendByte(0xa0);//写地址,发送要读哪个地址上的数据
    IIC_WaitAck();
    IIC_SendByte(add);
    IIC_WaitAck();
    
    IIC_Start();
    IIC_SendByte(0xa1);//读写控制信号为高电平时为读,所以最低位是1
    IIC_WaitAck();
    dat=IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    
    return dat;
}

程序控制

注意事项

  1. 两次写入操作时间间隔至少为5ms

  1. 全新的EEPROM内部存储的是0xff

//统计开机次数,每次上电数码管上的数字+1;

#include "system.h"
HexToBin led_ctrl,uln_ctrl;


void vSystem_Init(void)
{
    vDevice_Ctrl(0xa0,0);                 /* 关闭蜂鸣器、继电器*/
    led_ctrl.hex=0xff;
    vDevice_Ctrl(0x80,led_ctrl.hex);     /* 关闭LED*/
}

//开机次数统计
u8 start_times;
void vEEPROM_Process()
{
    start_times = ucRead_EEPROM(0x20);     /*AT24C02的地址范围是0x00~0xff*/
    vWrite_EEPROM(0x20,++start_times);
}

//数码管操作函数
void vSMG_Process()
{
    smg_buf[0]=smg_code[start_times/10];
    smg_buf[1]=smg_code[start_times%10];
    smg_buf[2]=0x00;
    smg_buf[3]=0x00;
    smg_buf[4]=0x00;
    smg_buf[5]=0x00;
    smg_buf[6]=0x00;
    smg_buf[7]=0x00;
}

void main(void)
{
    vSystem_Init();
    vEEPROM_Process();
    vTimer2_Init();
    while(1)
    {
        vSMG_Process();
    }
}


//中断服务程序
void vTimer2_ISR() interrupt 12         //中断入口
{
    vSMG_Display();
}

EEPROM读写不同类型数据

上面基础知识说了,一个地址,只能存入一个字节数据,所以针对不同类型的数据,必须分离成单个字节的数据

如果是两个字节的数据,就要拆成高8位和低8位数据

//EEPROM一个地址,只能存入一个字节的数据。针对不同类型的数据,需要分离成单个字节的数据。


#include "system.h"
HexToBin led_ctrl,uln_ctrl;


void vSystem_Init(void)
{
    vDevice_Ctrl(0xa0,0);                 /* 关闭蜂鸣器、继电器*/
    led_ctrl.hex=0xff;
    vDevice_Ctrl(0x80,led_ctrl.hex);     /* 关闭LED*/
}

//EEPROM处理函数
u16 u16_write = 1234;
u16 u16_read = 0;

float float_write = 3.1415;
float float_read = 0;

s8 minus_write = -23;
s8 minus_read = 0;

s16 minus_s16_write = -1234;
s16 minus_s16_read = 0;

u8 str_write[11]={"hello world"};
u8 str_read[11];
void vEEPROM_Process()
{
    u8 i = 0;
    
    /***************写入u16类型的数据**************/
    vWrite_EEPROM(0x00,u16_write>>8);
    vWrite_EEPROM(0x01,u16_write);
    u16_read = (ucRead_EEPROM(0x00)<<8)+ucRead_EEPROM(0x01);
    
    /***************写入float类型的数据,保留小数点后四位**************/
    vWrite_EEPROM(0x03,(u16)(float_write*1000)/256);
    vWrite_EEPROM(0x04,(u16)(float_write*1000)%256);
    float_read = (ucRead_EEPROM(0x03)*256+ucRead_EEPROM(0x04))/1000.0f;
    
    /***************写入负数,在数字电路中的存储形式是补码**************/
    /***************例如-23,其最高位为符号位1(表示负数),23的二进制10111,反码1110 1000,补码1110 1001 -> 0xE9**************/
    
    //    if(minus_write<0)
    //    {
    //        vWrite_EEPROM(0x06,'-');
    //        vWrite_EEPROM(0x07,-minus_write);
    //    }
    //    if(ucRead_EEPROM(0x06)=='-')
    //    {
    //        minus_read = 0 - ucRead_EEPROM(0x07);
    //    }
    
    vWrite_EEPROM(0x06,minus_write);
    minus_read = ucRead_EEPROM(0x06);    
    
    vWrite_EEPROM(0x08,minus_s16_write>>8);                        //取出高8位
    vWrite_EEPROM(0x09,minus_s16_write);                        //取出低8位
    minus_s16_read = (ucRead_EEPROM(0x08)<<8)+ucRead_EEPROM(0x09);
        
    /***************写入字符串,字符以ASCII码存储**************/
    for(i=0;i<sizeof(str_write);i++)
    {
        vWrite_EEPROM(0x10+i,str_write[i]);
    }
    for(i=0;i<sizeof(str_write);i++)
    {
        str_read[i]=ucRead_EEPROM(0x10+i);
    }
}

//数码管操作函数
void vSMG_Process()
{
    smg_buf[0]=0x00;
    smg_buf[1]=0x00;
    smg_buf[2]=0x00;
    smg_buf[3]=0x00;
    smg_buf[4]=0x00;
    smg_buf[5]=0x00;
    smg_buf[6]=0x00;
    smg_buf[7]=0x00;
}

void main(void)
{
    vSystem_Init();
    vEEPROM_Process();
    vTimer2_Init();
    while(1)
    {
        vSMG_Process();
    }
}


//中断服务程序
void vTimer2_ISR() interrupt 12         //中断入口
{
    vSMG_Display();
}

利用共用体读写EEPROM

利用共用体可以不用自己拆分多字节数据,可以实现自动拆分成单字节数据。

#include "system.h"
HexToBin led_ctrl,uln_ctrl;

void vSystem_Init(void)
{
    vDevice_Ctrl(0xa0,0);                 /* 关闭蜂鸣器、继电器*/
    led_ctrl.hex=0xff;
    vDevice_Ctrl(0x80,led_ctrl.hex);     /* 关闭LED*/
}

//EEPROM处理函数,利用共用体读写EEPROM
union eeprom_u16
{
   u16 a;  
   u8 b[2];
}u16_write,u16_read;

union eeprom_s16
{
   s16 a;  
   u8 b[2];
}s16_write,s16_read;

union eeprom_float
{
   float a;  
   u8 b[4];
}float_write,float_read;

union eeprom_u32
{
   u32 a;  
   u8 b[4];
}u32_write;

void vEEPROM_Process()
{
    u8 i = 0;
    
    /***************2个字节数据的读写*************/
    u16_write.a = 1234;
    for(i=0;i<sizeof(s16);i++)
    {
        vWrite_EEPROM(0x30+i,u16_write.b[i]);
    }
    for(i=0;i<sizeof(s16);i++)
    {
        u16_read.b[i]=ucRead_EEPROM(0x30+i);
    }
    
    /***************负数的读写*************/
    s16_write.a = -1234;
    for(i=0;i<sizeof(s16);i++)
    {
        vWrite_EEPROM(0x20+i,s16_write.b[i]);
    }
    for(i=0;i<sizeof(s16);i++)
    {
        s16_read.b[i]=ucRead_EEPROM(0x20+i);
    }
    
    /***************float小数的读写**************/
    float_write.a = 3.1415926;
    for(i=0;i<sizeof(float);i++)
    {
        vWrite_EEPROM(0x10+i,float_write.b[i]);    
    }
    for(i=0;i<sizeof(float);i++)
    {
        float_read.b[i]=ucRead_EEPROM(0x10+i);
    }
}

//数码管操作函数
void vSMG_Process()
{
    smg_buf[0]=0x00;
    smg_buf[1]=0x00;
    smg_buf[2]=0x00;
    smg_buf[3]=0x00;
    smg_buf[4]=0x00;
    smg_buf[5]=0x00;
    smg_buf[6]=0x00;
    smg_buf[7]=0x00;
}

void main(void)
{
    vSystem_Init();
    vEEPROM_Process();
    vTimer2_Init();
    while(1)
    {
        vSMG_Process();
    }
}


//中断服务程序
void vTimer2_ISR() interrupt 12         //中断入口
{
    vSMG_Display();
}

以上所有工程文件见百度云

链接:https://pan.baidu.com/s/1p95KCRzdqfjCsS7-pO6lyg

提取码:1815

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值