4.6 51单片机-EEPROM存储芯片(AT24C02)

4.6 EEPROM存储芯片(AT24C02)

4.6.1 原理图介绍

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-1

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-2

实验板上的EEPROM型号是AT24C02N,通信接口是IIC,接在单片机的P2.1(SCL)和P2.2(SDA) 口上。

AT24C02是一颗2kbit(256字节)的EEPROM。

实验板的原理图上描述是24C16,实际实验板上使用的具体芯片型号是AT24C02。

4.6.2 AT24C02介绍

AT24C02是一个2K位串行EEPROM,内部含有256个字节空间。AT24C02内部有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。

I2C总线是由 PHILIPS(飞利浦) 公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点(这个速率高指的是和它同时代的通信总线)。

特性:

(1)、传送速率为400KHz和IIC总线兼容

(2)、2.7V至7V的工作电压

(3)、8字节页写缓冲区

(4)、100万次擦写周期

(5)、数据保存可达100年

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-3 AT24C02封装图与引脚功能介绍

管脚上的A0、A1、A2是地址配置引脚,以组成000~111八种情况,通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上。 SDA是IIC总线的数据线,SCL是IIC总线的时钟线。

AT24C02内部的设备地址是:1010  ,下面图片里2K就是AT2C02的对应地址。

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-4 AT24C02设备地址

AT24C02的一个写周期时间为10ms,单片机向AT24C02传输数据时,AT24C02是将数据暂存在8字节的缓冲区里的,单片机发送完数据之后需要等待10ms的时间,等待AT24C02将缓冲区的数据存到内部EEPROM里,存放到EEPROM之后,掉电才不会丢失。

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-5 写周期时间

4.6.3 AT24C02时序介绍

(1) 总线时序图

4.6 51单片机-EEPROM存储芯片(AT24C02)

 图4-6-6 总线时序

(2) 起始信号与停止信号时序图

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-7 起始信号与停止信号时序

当时钟线为高电平的时候,数据线由高电平变为低电平的过程。

IIC_SCL=1;
IIC_SDA=1;
IIC_SDA=0;
IIC_SCL=0; //总线开始工作、开始读写数据

 当时钟线为高电平的时候,数据线由低电平变为高电平的过程。

IIC_SCL=0;
IIC_SDA=0;
IIC_SCL=1;
IIC_SDA=1;

 (3) 应答信号时序图

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-8 应答时序图

有效应答信号是低电平。

(4) 数据位的传输时序图

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-9 数据的有效性

输出传输从高位开始。

/*函数功能: 发送一个字节数据*/
void IIC_SendOneByte(u8 dat)
{
    u8 j=0,i=0;
    for(j=0;j<8;j++)
    {
        IIC_SCL=0;
        if(dat&0x80)IIC_SDA=1;
        else IIC_SDA=0;
        IIC_SCL=1;
        dat<<=1;
    }
IIC_SCL=0;
}

(5) AT24C02写一个字节的总时序

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-10

(6) AT24C02写一页数据的总时序

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-11

(7) 从AT24C02当前地址读取一个字节的总时序

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-12

(8). 从AT24C02指定位置读取指定长度数据的总时序

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-13

4.6.4 AT24C02读写数据示例代码

下面代码演示了AT24C02写入数据和读取数据的过程,在主函数里,调用AT24C02写字节函数向指定空间存入数据,再调用读函数读出来,打印到串口终端。

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:

#include <reg51.h>
/*
说明: 在12MHZ晶振下,12T模式下,i++消耗的时间差不多是12us
*/
/*
硬件连接: 
    SCL---P2.1
    SDA---P2.0
*/
//数据线
sbit IIC_SDA=P2^0;
//时钟线
sbit IIC_SCL=P2^1;

/*
函数功能: 发送起始信号
当时钟线为高电平的时候,数据线由高电平变为低电平的过程
*/
void IIC_SendStart(void)
{
    u8 i=0;
    IIC_SCL=1;
    IIC_SDA=1;
    IIC_SDA=0;
    IIC_SCL=0; //总线开始工作、开始读写数据
}

/*
函数功能: 停止信号
当时钟线为高电平的时候,数据线由低电平变为高电平的过程
*/
void IIC_SendStop(void)
{
    u8 i=0;
    IIC_SCL=0;
    IIC_SDA=0;
    IIC_SCL=1;
    IIC_SDA=1;
}

/*
函数功能: 获取应答信号
返 回 值: 0表示获取到应答 1表示没有获取到应答
*/
u8 IIC_GetAck(void)
{
    u8 i=0;
    IIC_SDA=1; //上拉
    IIC_SCL=0;
    IIC_SCL=1;
    while(IIC_SDA)
    {
        i++;
        if(i>250)return 1; //获取不到应答
    }
    IIC_SCL=0;
    return 0;
}

/*
函数功能: 发送应答信号
函数参数:0表示应答 1表示非应答
*/
void IIC_SendAck(u8 ack)
{
    u8 i=0;
    IIC_SCL=0;
    if(ack)IIC_SDA=1; //发送非应答
    else IIC_SDA=0; //发送应答
    IIC_SCL=1;
    IIC_SCL=0;
}

/*
函数功能: 发送一个字节数据
*/
void IIC_SendOneByte(u8 dat)
{
    u8 j=0,i=0;
    for(j=0;j<8;j++)
    {
        IIC_SCL=0;
        if(dat&0x80)IIC_SDA=1;
        else IIC_SDA=0;
        IIC_SCL=1;
        dat<<=1;
    }
    IIC_SCL=0;
}

/*
函数功能: 接收一个字节数据
*/
u8 IIC_RecvOneByte(void)
{
    u8 i=0,j=0;
    u8 dat=0;
    for(j=0;j<8;j++)
    {
        IIC_SCL=0;
        IIC_SCL=1;
        dat<<=1; //表示默认收到0
        if(IIC_SDA)dat|=0x01;
    }
    IIC_SCL=0;
    return dat;
}
/*
函数功能: 写一个字节
函数参数:
    u8 addr 数据的位置(0~255)
    u8 dat 数据范围(0~255)
*/
void AT24C02_WriteOneByte(u16 addr,u8 dat)
{
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_WRITE_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    IIC_SendOneByte(addr); //数据存放的地址
    IIC_GetAck();//获取应答
    IIC_SendOneByte(dat); //发送将要存放的数据
    IIC_GetAck();//获取应答
    IIC_SendStop(); //停止信号
    DelayMs(10); //等待写
}

/*
函数功能: 读一个字节
函数参数:
    u8 addr 数据的位置(0~255)
返回值: 读到的数据
*/
u8 AT24C02_ReadOneByte(u16 addr)
{
    u8 dat=0;
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_WRITE_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    IIC_SendOneByte(addr); //将要读取数据的地址
    IIC_GetAck();//获取应答
    
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_READ_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    dat=IIC_RecvOneByte();//读取数据
    IIC_SendAck(1); //发送非应答
    IIC_SendStop(); //停止信号
    return dat;
}

/*
函数功能: 从指定位置读取指定长度的数据
函数参数:
    u16 addr 数据的位置(0~255)
    u16 len 读取的长度
    u8 *buffer 存放读取的数据
返回值: 读到的数据
*/
void AT24C02_ReadByte(u16 addr,u16 len,u8 *buffer)
{
    u16 i=0;
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_WRITE_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    IIC_SendOneByte(addr); //将要读取数据的地址
    IIC_GetAck();//获取应答
    
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_READ_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    for(i=0;i<len;i++)
    {
        buffer[i]=IIC_RecvOneByte();//读取数据
        if(i<len-1)IIC_SendAck(0); //发送应答
        else IIC_SendAck(1); //发送非应答
    }
    IIC_SendStop(); //停止信号
}

/*
函数功能: AT24C02页写函数
函数参数:
    u16 addr 写入的位置(0~1023)
    u8 len 写入的长度(每页16字节)
    u8 *buffer 存放读取的数据
*/
void AT24C02_PageWrite(u16 addr,u16 len,u8 *buffer)
{
    u16 i=0;
    IIC_SendStart();//起始信号
    IIC_SendOneByte(AT24C02_WRITE_ADDR);//发送设备地址
    IIC_GetAck();//获取应答
    IIC_SendOneByte(addr); //数据存放的地址
    IIC_GetAck();//获取应答
    for(i=0;i<len;i++)
    {
        IIC_SendOneByte(buffer[i]); //发送将要存放的数据
        IIC_GetAck();//获取应答 
    }
    IIC_SendStop(); //停止信号
    DelayMs(10); //等待写
}

/*
函数功能: 从指定位置写入指定长度的数据
函数参数:
    u16 addr 数据的位置(0~255)
    u16 len 写入的长度
    u8 *buffer 存放即将写入的数据
返回值: 读到的数据
*/
void AT24C02_WriteByte(u16 addr,u16 len,u8 *buffer)
{
    u8 page_byte=8-addr%8; //得到当前页剩余的字节数量
    if(page_byte>len) //判断当前页剩余的字节空间是否够写
    {
        page_byte=len; //表示一次性可以写完
    }
    while(1)
    {
        AT24C02_PageWrite(addr,page_byte,buffer); //写一页
        if(page_byte==len)break; //写完了
        buffer+=page_byte; //指针偏移
        addr+=page_byte;//地址偏移
        len-=page_byte;//得到剩余没有写完的长度
        if(len>8)page_byte=8;
        else page_byte=len; //一次可以写完
    }
}

//u8 at24c02_w[8]="1234567";
//u8 at24c02_r[8];
int main()
{
    u8 dat;
    UART_Init();        //初始化串口波特率为4800
    while(1)
    {
//单个字节读写测试
        AT24C02_WriteOneByte(10,34);
        dat=AT24C02_ReadOneByte(10);
        printf("dat=%d\r\n",(int)dat);
        //多个字节读写测试
        //AT24C02_WriteByte(0,8,at24c02_w);
//        AT24C02_ReadByte(0,8,at24c02_r);
//        printf("at24c02_r=%s\r\n",at24c02_r);
          DelayMs(1000);
}
}

 4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-13

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-14 逻辑分析仪检测的写时序过程

4.6 51单片机-EEPROM存储芯片(AT24C02)

图4-6-15 逻辑分析仪检测的读时序过程

上一篇:使用ODBC连接MySQL和EXCEL


下一篇:BH1750光强度传感器Stm32f103驱动(已测试ok)