• 【mcuclub】数据存储AT24C02


    一、实物图

    二、原理图

    编号名称功能
    1A0

    地址输入。A2、A1和A0是器件地址输入引脚。

    24C02/32/64使用A2、A1和AO输入引脚作为硬件地址,总线上可同时级联8个24C02/32/64器件。

    24C04使用A2和A1输入引脚作为硬件地址,总线上可同时级联4个24CO4器件,A0为空脚,可接地。

    24C08使用A2输入引脚作为硬件地址,总线上可同时级联2个24C08器件,AO和A1为空脚,可接地。

    24C16未使用器件地址引脚,总线上最多只可连接一个16K器件,A2、A1和A0为空脚,可接地。

    2A1
    3A2
    4GND电源地
    5SDA串行地址和数据输入/输出。SDA是双向串行数据传输引脚,漏极开路,需要外接上拉电阻到VCC(典型值10k)。
    6SCL串行时钟输入。SCL同步数据传输,上升沿数据写入,下降沿数据读出。
    7WP写保护。WP引脚提供硬件数据保护。当WP接地时,允许数据正常读写操作;当WP接VCC时,写保护,只读。
    8VCC电源正(1.8~5.5V)

    三、简介

    AT24C02是美国Atmel公司的低功耗CMOS型E2PROM,内含256*8位存储空间;具有工作电压宽(1.8V~5.5V):擦写次数多(大于10000次):写入速度快(小于10ms),抗干扰能力强,数据不易丢失,体积小等特点。并且它是采用I2C总线式进行数据读写的串行操作,只占用很少的资源和I/O线。

    四、内部结构框图

    五、寻址方式

    AT24C02的存储容量为2K bit,内容分成32页,每页8Byte,共256Byte,操作时有两种寻址方式:芯片寻址和片内子地址寻址。

    (1)芯片寻址:AT24C02的芯片地址为1010,其地址控制字格式为1010 A2 A1 A0 R/W。其中A2,A1,A0可编程地址选择位。A2,A1,A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该器件的地址码。R/W为芯片读写控制位,该位为0,表示芯片进行写操作;该位为1,表示芯片进行读操作。

    (2)片内子地址寻址:芯片寻址可对内部256Byte中的任意一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。

    六、通信协议(I2C通信)

    1、I2C总线介绍

    <1>I2C总线(Inter IC bus)是由Philips公司开发的一种通用数据总线。

    <2>两根通信线:SCL(Serial Clock串行时钟线)、SDA(Serial Data串行数据线)。

    <3>同步、半双工,带数据应答。

    *注:同步(因为它有单独的时钟线)、半双工(SDA只有一根线,并且还要来回通信)

    <4>通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度。

    2、I2C电路规范

    <1>所有I2C设备的SCL连在一起,SDA连在一起

    <2>设备的SCL和SDA均要配置成开漏输出模式(硬件IIC)

    *开漏输出模式——断开时引脚成浮空状态(电路断开,电压不稳定)

    <3>SCL和SDA各添加一个上拉电阻,阻值一般为4.7K~10K左右

    <4>开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题。

    3、I2C时序结构

    起始信号:SCL高电平期间,SDA从高电平切换到低电平

    停止信号:SCL高电平期间,SDA从低电平切换到高电平

    代码如下:

    /****

    *******I2C总线启动信号

    *****/

    void AT24C02_IIC_Start(void)

    {

       AT24C02_SDA = 1;

       AT24C02_SCL = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

       AT24C02_SDA = 0;

       AT24C02_IIC_Delay(DELAY_TIME);

       AT24C02_SCL = 0;

    }

    /****

    *******I2C总线停止信号

    *****/

    void AT24C02_IIC_Stop(void)

    {

       AT24C02_SDA = 0;

       AT24C02_SCL = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

       AT24C02_SDA = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

    }

    发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。

    接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)。

    代码如下:

    /****

    *******发送应答或非应答信号

    *****/

    void AT24C02_IIC_SendAck(bit ackbit)

    {

       AT24C02_SCL = 0;

       AT24C02_SDA = ackbit;

       AT24C02_IIC_Delay(DELAY_TIME);

       AT24C02_SCL = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

       AT24C02_SCL = 0;

       AT24C02_SDA = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

    }

    /****

    *******等待应答信号

    *****/

    bit AT24C02_IIC_WaitAck(void)

    {

       bit ackbit;

       AT24C02_SDA = 1;

       AT24C02_SCL = 1;

       AT24C02_IIC_Delay(DELAY_TIME);

       ackbit = AT24C02_SDA;

       AT24C02_SCL = 0;

       AT24C02_IIC_Delay(DELAY_TIME);

       return ackbit;

    }

    发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。

    代码如下:

    /****

    *******I2C总线发送一个字节数据

    *****/

    void AT24C02_IIC_SendByte(uchar byte)

    {

       uchar i;

       AT24C02_SCL = 0;

       for(i=0; i<8; i++)

       {

          if(byte & 0x80)

             AT24C02_SDA = 1;

          else

             AT24C02_SDA = 0;

          AT24C02_IIC_Delay(DELAY_TIME);

          AT24C02_SCL = 1;

          AT24C02_IIC_Delay(DELAY_TIME);

          AT24C02_SCL = 0;

          AT24C02_IIC_Delay(DELAY_TIME);

          byte <<= 1;

       }

       AT24C02_IIC_WaitAck();

    }

    接收一个字节:SCL低电平期间,从机将数据位依次放到SDA总线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

    代码如下:

    /****

    *******I2C总线接收一个字节数据

    *****/

    uchar AT24C02_IIC_RecByte(bit ackbit)

    {

       uchar i, dat;

       AT24C02_SDA = 1;

       for(i=0; i<8; i++)

       {

          AT24C02_SCL = 1;

          AT24C02_IIC_Delay(DELAY_TIME);

          dat <<= 1;

          if(AT24C02_SDA)

             dat |= 1;

          AT24C02_SCL = 0;

          AT24C02_IIC_Delay(DELAY_TIME);

       }

       AT24C02_IIC_SendAck(ackbit);

       return dat;

    }

    4、AT24C02数据帧

    AT24C02的固定地址为1010,本设计A2 A1 A0都接地,所以SLAVE ADDRESS+W为0xA0(1010 000 0),SLAVE ADDDRESS+R为0xA1(1010 000 1)

    字节写:在“字地址”处写入“数据”

    代码如下:

    /****

    *******向AT24C02的地址address中写入一个字节的数据

    *****/

    void At24c02_Write_Data(uchar address,uchar dat)

    {

       AT24C02_IIC_Start();

       AT24C02_IIC_SendByte(AT24C02_SlaveAddress);

       AT24C02_IIC_SendByte(address);

       AT24C02_IIC_SendByte(dat);

       AT24C02_IIC_Stop();

    }

    随机读:读出在“字地址”处的“数据”

    代码如下:

    /****

    *******从AT24C02的地址address中读取一个字节的数据

    *****/

    uchar At24c02_Read_Data(uchar address)

    {

       uchar dat;

       AT24C02_IIC_Start();

       AT24C02_IIC_SendByte(AT24C02_SlaveAddress);

       AT24C02_IIC_SendByte(address);

       AT24C02_IIC_Start();

       AT24C02_IIC_SendByte(AT24C02_SlaveAddress + 1);

       dat = AT24C02_IIC_RecByte(AT24C02_ACK);

       AT24C02_IIC_Stop();

       return(dat);

    }

    七、流程设计

    首先初始化引脚,然后判断是写数据还是读数据,如果是写数据,则首先启动I2C总线,然后发送器件写地址,等待应答,接下来发送数据地址,等待应答,再接下来写入数据,等待应答,最后关闭I2C总线。如果是读数据,则首先启动I2C总线,然后发送器件写地址,等待应答,接下来发送目标地址,等待应答,再次启动I2C总线,然后发送器件读地址,等待应答,接下来读取数据,发送应答,最后关闭I2C总线。

  • 相关阅读:
    ChatGPT的前世今生:从概念到现实的AI之旅
    C语言:数组(超级详细讲解)
    亚商投资顾问 早餐FM/1124金融16条出炉
    微信小程序语法总结
    实验7 Spark初级编程实践
    誉天在线项目~ElementPlus Tag标签用法
    DHorse系列文章之操作手册
    SpringMvc(三、REST风格快速入门
    安装和初步使用 nn-Meter
    【Hadoop】MapReduce详解
  • 原文地址:https://blog.csdn.net/weixin_61121477/article/details/127745689