ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-11-30 20:02:59  阅读:356  来源: 互联网

标签:SCL 4.6 u8 51 存储芯片 时序 AT24C02 IIC SDA


4.6 EEPROM存储芯片(AT24C02)

4.6.1 原理图介绍

图4-6-1

图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-3 AT24C02封装图与引脚功能介绍

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

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

图4-6-4 AT24C02设备地址

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

图4-6-5 写周期时间

4.6.3 AT24C02时序介绍

(1) 总线时序图

 图4-6-6 总线时序

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

图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-8 应答时序图

有效应答信号是低电平。

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

图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-10

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

图4-6-11

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

图4-6-12

(8). 从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-13

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

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

标签:SCL,4.6,u8,51,存储芯片,时序,AT24C02,IIC,SDA
来源: https://blog.csdn.net/xiaolong1126626497/article/details/121031506

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有