STM32速成笔记—EEPROM(AT24C02)

2024-07-13 1043阅读

🎀 文章作者:二土电子

🌸 关注文末公众号获取其他资料和工程文件!

🐸 期待大家一起学习交流!



文章目录

  • 一、AT24C02简介
  • 二、AT24C02引脚
  • 三、AT24C02寻址
  • 四、AT24C02读/写操作
    • 4.1 AT24C02写操作
    • 4.2 AT24C02读操作
    • 五、AT24C02程序
    • 六、应用实例
    • 七、拓展应用

      一、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引脚

      STM32速成笔记—EEPROM(AT24C02)

      三、AT24C02寻址

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

      STM32速成笔记—EEPROM(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),接着必须由主器件发送停止条件来终止写序列。时序图如下

      STM32速成笔记—EEPROM(AT24C02)

      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",但需发送停止条件。当前地址读操作时序图如下

        STM32速成笔记—EEPROM(AT24C02)

        • 随机读

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

          STM32速成笔记—EEPROM(AT24C02)

          • 顺序读

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

            STM32速成笔记—EEPROM(AT24C02)

            五、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              
                    if((txd&0x80)0) //0x80  1000 0000
            			IIC_SDA=1;
            		else
            			IIC_SDA=0;
                    txd
            	u8 i,receive=0;
            	SDA_IN();//SDA设置为输入
                for(i=0;i
                    IIC_SCL=0; 
                    delay_us(2);
            		IIC_SCL=1;
                    receive
            	IIC_Init();//IIC初始化
            }
            /*******************************************************************************
            * 函 数 名         : AT24CXX_ReadOneByte
            * 函数功能		   : 在AT24CXX指定地址读出一个数据
            * 输    入         : ReadAddr:开始读数的地址 
            * 输    出         : 读到的数据
            *******************************************************************************/
            u8 AT24CXX_ReadOneByte(u16 ReadAddr)
            {				  
            	u8 temp=0;		  	    																 
                IIC_Start();  
            	if(EE_TYPEAT24C16)
            	{
            		IIC_Send_Byte(0XA0);	   //发送写命令
            		IIC_Wait_Ack();
            		IIC_Send_Byte(ReadAddr8);//发送高地址	    
            	}
            	else 
            	{
            		IIC_Send_Byte(0XA0+((ReadAddr/256)				   	  	    																 
                IIC_Start();  
            	if(EE_TYPEAT24C16)
            	{
            		IIC_Send_Byte(0XA0);	    //发送写命令
            		IIC_Wait_Ack();
            		IIC_Send_Byte(WriteAddr8);//发送高地址	  
            	}
            	else 
            	{
            		IIC_Send_Byte(0XA0+((WriteAddr/256)  	
            	u8 t;
            	for(t=0;t
            		AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite(8*t))&0xff);
            	}												    
            }
            /*******************************************************************************
            * 函 数 名         : AT24CXX_ReadLenByte
            * 函数功能		   : 在AT24CXX里面的指定地址开始读出长度为Len的数据
            					 用于读出16bit或者32bit的数据
            * 输    入         : ReadAddr   :开始读出的地址 
            					 Len        :要读出数据的长度2,4
            * 输    出         : 读取的数据
            *******************************************************************************/
            u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
            {  	
            	u8 t;
            	u32 temp=0;
            	for(t=0;t
            		temp
            	u8 temp;
            	temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX			   
            	if(temp==0x36)return 0;		   
            	else//排除第一次初始化的情况
            	{
            		AT24CXX_WriteOneByte(255,0X36);
            	    temp=AT24CXX_ReadOneByte(255);	  
            		if(temp==0X36)return 0;
            	}
            	return 1;											  
            }
            /*******************************************************************************
            * 函 数 名         : AT24CXX_Read
            * 函数功能		   : 在AT24CXX里面的指定地址开始读出指定个数的数据
            * 输    入         : ReadAddr :开始读出的地址 对24c02为0~255
            					 pBuffer  :数据数组首地址
            					 NumToRead:要读出数据的个数
            * 输    出         : 无
            *******************************************************************************/
            void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
            {
            	while(NumToRead)
            	{
            		*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);	
            		NumToRead--;
            	}
            } 
            /*******************************************************************************
            * 函 数 名         : AT24CXX_Write
            * 函数功能		   : 在AT24CXX里面的指定地址开始写入指定个数的数据
            * 输    入         : WriteAddr :开始写入的地址 对24c02为0~255
            					 pBuffer  :数据数组首地址
            					 NumToRead:要读出数据的个数
            * 输    出         : 无
            *******************************************************************************/
            void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
            {
            	while(NumToWrite--)
            	{
            		AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
            		WriteAddr++;
            		pBuffer++;
            	}
            }
            
            		printf("AT24C02检测不正常!\r\n");
            		delay_ms(500);
            	}
            	printf("AT24C02检测正常!\r\n");
            
            	Med_Mcu_Iint();   // 系统初始化
            	
            	AT24CXX_WriteOneByte(0,gWData);
            	printf("写入的数据是:%d\r\n",gWData);
            	
            	gRData = AT24CXX_ReadOneByte(0);
            	printf("读取的数据是:%d\r\n",gRData);
            	
            	while(1)
              {
            	}
            }
            
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]