STM32速成笔记(11)—EEPROM(AT24C02)

发布时间:2024-05-15  

一、AT24C02简介

AT24C01/02/04/08/16...是一个1K/2K/4K/8K/16K位电可擦除PROM,内部含有128/256/512/1024/2048个8位字节,AT24C01有一个8字节页写缓冲器,AT24C02/04/08/16有一个16字节页写缓冲器。

电压可允许低至1.8V,待机电流和工作电流分别为1uA和1mA。该器件通过I2C总线接口进行操作,这里就不再对IIC做详细介绍了,具体可见外设系列OLED篇。


二、AT24C02引脚

图片

AT24C02引脚定义

三、AT24C02寻址

使能芯片读写操作后,EEPROM都要求有8位的器件地址信息。

图片

AT24C02地址信息

器件地址信息由"1"、"0"序列组成,前4位对于所有串行EEPROM都是一样的。对于24C02/32/64,随后3位A2、A1和A0为器件地址位,必须与硬件输入引脚保持一致。

四、AT24C02读/写操作

4.1 AT24C02写操作

写操作要求主设备发送器件地址,收到应答信号后,先接收8位的字地址。接收到这个地址后EEPROM应答"0"(ACK),然后再是一个8位数据。在接收8位数据后,EEPROM应答"0"(ACK),接着必须由主器件发送停止条件来终止写序列。时序图如下

图片

写操作时序图

24C02器件按8字节/页执行页写,24C04/08/16器件按16字节/页执行页写,24C32/64器件按32字节/页执行页写。页写初始化与字节写相同,只是主器件不会在第一个数据后发送停止条件,而是在EEPROMEEPROM收到每个数据后都应答“0”。最后仍需由主器件发送停止条件,终止写序列。

接收到每个数据后,字地址的低3位 (24C02) 或4位(24C04/08/16) 或5位(24C32/64)内部自动加1,高位地址位不变,维持在当前页内。当内部产生的字地址达到该页边界地址时,随后的数据将写入该页的页首。如果超过8个 (24C02) 或16个 (24C04/08/16) 或32个(24C32/64) 数据传送给了EEPROM,字地址将回转到该页的首字节,先前的字节将会被覆盖。

4.2 AT24C02读操作

AT24C02的读操作有三种,分别是当前地址读,随机读和顺序读。

  • • 当前地址读 内部地址计数器保存着上次访问时最后一个地址加1的值。只要芯片有电,该地址就一直保存当读到最后页的最后字节,地址会回转到0。当写到某页尾的最后一个字节,地址会回转到该页的首字节。接收器件地址(读/写选择位为"1") 且EEPROM应答ACK后,当前地址的数据就随时钟送出。主器件无需应答"0",但需发送停止条件。当前地址读操作时序图如下

图片

读当前地址时序图

  • • 随机读 随机读需先写一个目标字地址,一旦EEPROM接收器件地址和字地址并应答了ACK,主器件就产生一个重复的起始条件。然后,主器件发送器件地址(读/写选择位为"1") ,EEPROM应答ACK,并随时钟送出数据。主器件无需应答"0",但需发送停止条件。这里的随机读就是读取任意一个字地址的数据,并不是随即返回一个数据的意思。随机读时序图如下

图片

随机读时序图

  • • 顺序读 顺序读可以通过“当前地址读”或“随机读”启动。主器件接收到一个数据后,应答ACK。只要EEPROM接收到ACK,将自动增加字地址并继续随时钟发送后面的数据。若达到存储器地址末尾,地址自动回转到0,仍可继续顺序读取数据。主器件不应答"0",而发送停止条件,即可结束顺序读操作。顺序读时序图如下

图片

顺序读时序图


五、AT24C02程序

这里给出一个AT24C02的程序,仅供参考


/*******************************************************************************

* 函 数 名         : IIC_Init

* 函数功能     : IIC初始化

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void IIC_Init(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC|IIC_SDA_PORT_RCC,ENABLE);

    

    GPIO_InitStructure.GPIO_Pin=IIC_SCL_PIN;

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

    GPIO_Init(IIC_SCL_PORT,&GPIO_InitStructure);

    

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;

    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);

    

    IIC_SCL=1;

    IIC_SDA=1; 

}

/*******************************************************************************

* 函 数 名         : SDA_OUT

* 函数功能     : SDA输出配置    

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void SDA_OUT(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);

}


/*******************************************************************************

* 函 数 名         : SDA_IN

* 函数功能     : SDA输入配置    

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void SDA_IN(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);

}


/*******************************************************************************

* 函 数 名         : IIC_Start

* 函数功能     : 产生IIC起始信号   

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void IIC_Start(void)

{

    SDA_OUT();     //sda线输出

    IIC_SDA=1;      

    IIC_SCL=1;

    delay_us(5);

     IIC_SDA=0;//START:when CLK is high,DATA change form high to low 

    delay_us(6);

    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 


/*******************************************************************************

* 函 数 名         : IIC_Stop

* 函数功能     : 产生IIC停止信号   

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void IIC_Stop(void)

{

    SDA_OUT();//sda线输出

    IIC_SCL=0;

    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

     IIC_SCL=1; 

    delay_us(6); 

    IIC_SDA=1;//发送I2C总线结束信号

    delay_us(6);           

}


/*******************************************************************************

* 函 数 名         : IIC_Wait_Ack

* 函数功能     : 等待应答信号到来   

* 输    入         : 无

* 输    出         : 1,接收应答失败

                     0,接收应答成功

*******************************************************************************/

u8 IIC_Wait_Ack(void)

{

    u8 tempTime=0;

    SDA_IN();      //SDA设置为输入  

    IIC_SDA=1;

    delay_us(1);    

    IIC_SCL=1;

    delay_us(1);  

    while(READ_SDA)

    {

        tempTime++;

        if(tempTime >250)

        {

            IIC_Stop();

            return 1;

        }

    }

    IIC_SCL=0;//时钟输出0     

    return 0;  


/*******************************************************************************

* 函 数 名         : IIC_Ack

* 函数功能     : 产生ACK应答  

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void IIC_Ack(void)

{

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=0;

    delay_us(2);

    IIC_SCL=1;

    delay_us(5);

    IIC_SCL=0;

}


/*******************************************************************************

* 函 数 名         : IIC_NAck

* 函数功能     : 产生NACK非应答  

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/      

void IIC_NAck(void)

{

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=1;

    delay_us(2);

    IIC_SCL=1;

    delay_us(5);

    IIC_SCL=0;


/*******************************************************************************

* 函 数 名         : IIC_Send_Byte

* 函数功能     : IIC发送一个字节 

* 输    入         : txd:发送一个字节

* 输    出         : 无

*******************************************************************************/    

void IIC_Send_Byte(u8 txd)

{                        

    u8 t;   

    SDA_OUT();      

    IIC_SCL=0;//拉低时钟开始数据传输

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

    {              

        if((txd&0x80) >0) //0x80  1000 0000

            IIC_SDA=1;

        else

            IIC_SDA=0;

        txd< <=1;    

        delay_us(2);   //对TEA5767这三个延时都是必须的

        IIC_SCL=1;

        delay_us(2); 

        IIC_SCL=0; 

        delay_us(2);

    }  


/*******************************************************************************

* 函 数 名         : IIC_Read_Byte

* 函数功能     : IIC读一个字节 

* 输    入         : ack=1时,发送ACK,ack=0,发送nACK 

* 输    出         : 应答或非应答

*******************************************************************************/  

u8 IIC_Read_Byte(u8 ack)

{

    u8 i,receive=0;

    SDA_IN();//SDA设置为输入

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

    {

        IIC_SCL=0; 

        delay_us(2);

        IIC_SCL=1;

        receive< <=1;

        if(READ_SDA)receive++;   

        delay_us(1); 

    }      

    if (!ack)

        IIC_NAck();//发送nACK

    else

        IIC_Ack(); //发送ACK   

    return receive;

}

/*******************************************************************************

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>