STM32 (基于HAL库) 硬件IIC任意地址读写任意字节—-AT24CXX芯片

STM32 (基于HAL库) 硬件IIC任意地址读写任意字节—-AT24CXX芯片

EEPROM芯片读写程序相关索引

1.AT24C04、AT24C08、AT24C16系列EEPROM芯片单片机读写驱动程序
2.STM32 (基于HAL库) 硬件IIC读写任意AT24CXX芯片

一、概述

转了一圈,发现有关STM32的iic的硬件是使用比较少,基于HAL库的就更少,传统的,大家都是采用软件模拟的。由于iic的协议相对复杂,同时灵活,尤其是不同的设备的I2C通信组合变化也不同,使用灵活的软件模拟也是可以理解的,在加上I2C的设备读写速度都比较低,硬件读写的优势就更无法体现,哪怕硬件I2C可以开启DMA,甚至在随机的读取少量字节的情况下。开启DMA反而效果更差。自然而然的硬件I2C就无人问津了。只是最近在学习HAL库的开发,本想着学习的态度,加上开发版上自带AT24C04的EEPROM芯片,以及引脚以链接硬件的I2C的引脚,就学习一下使用硬件I2C,在此非常感谢,“相关索引”的两位作者,通过上面的两篇文章,参考及学习才有我的AT24CXX芯片任意地址读写任意字节的代码。

二、代码分享

代码逻辑很简单,通读一遍代码基本解可以理解了,加上代码的注释,基本就可以明白了。在这我就不班门弄斧多加解释了!唯一需要说明的是写操作要用HAL库的阻塞模式下的I2C的硬件库函数(HAL_I2C_Mem_Write ),而读操作要用非阻塞模式的库函数(HAL_I2C_Master_Receive),不然硬件的I2C对 EEPROM芯片读写格式不符合芯片规定格式,无法正常读取,这里与“嵌入式设计开发er”作者的代码有点出入。理论上,分享的代码适用于AT24C02、AT24C04、AT24C08、AT24C16系列EEPROM芯片,实际验证于AT24C04芯片。至于更高容量的待验证,或者感兴趣的朋友可以自行验证,有问题可以邮件联系我!联系邮箱为:tcxfjt@126.com

24CXX.h文件代码如下:

#ifndef AT24CXX_H__
#define AT24CXX_H__
/*****************************************
本驱动文件仅适配HAL库版本
作者:痕迹(Hamaliel)
******************************************/
#include "stm32f1xx_hal.h"	//链接HAL库
#include "./SYSTEM/sys/sys.h"
/* Exported constants (常量) --------------------------------------------------------*/


/* Exported macro (宏) --------------------------------------------------------------*/
#define READ_CMD                1
#define WRITE_CMD               0
#define USE_HARDWARE_IIC        1
#define x24C04//器件名称,x24C04、x24C08或x24C16
#define DEV_ADDR                0xA0                    //设备硬件地址

#ifdef x24C04
    #define PAGE_NUM            32                      //页数
    #define PAGE_SIZE           16                      //页面大小(字节)
    #define CAPACITY_SIZE       (PAGE_NUM * PAGE_SIZE)  //总容量(字节)
    #define ADDR_BYTE_NUM       1                       //地址字节个数
#endif
 
#ifdef x24C08
    #define PAGE_NUM            64                      //页数
    #define PAGE_SIZE           16                      //页面大小(字节)
    #define CAPACITY_SIZE       (PAGE_NUM * PAGE_SIZE)  //总容量(字节)
    #define ADDR_BYTE_NUM       1                       //地址字节个数
#endif
 
#ifdef x24C16
    #define PAGE_NUM            128                     //页数
    #define PAGE_SIZE           16                      //页面大小(字节)
    #define CAPACITY_SIZE       (PAGE_NUM * PAGE_SIZE)  //总容量(字节)
    #define ADDR_BYTE_NUM       1                       //地址字节个数
#endif

#define AT24C01     127
#define AT24C02     255
#define AT24C04     511
#define AT24C08     1023
#define AT24C16     2047
#define AT24C32     4095
#define AT24C64     8191
#define AT24C128    16383
#define AT24C256    32767  
//我使用的是AT24C04,容量4kbit(512byte)地址范围0~511

/* I2C1 引脚 定义 */
#define I2C1_SCL_GPIO_PORT              GPIOB
#define I2C1_SCL_GPIO_PIN               GPIO_PIN_6
#define I2C1_SCL_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */

#define I2C1_SDA_GPIO_PORT              GPIOB
#define I2C1_SDA_GPIO_PIN               GPIO_PIN_7
#define I2C1_SDA_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */

/* I2C1 相关定义 */
#define I2C1_I2C                        I2C1
#define I2C1_I2C_CLK_ENABLE()           do{ __HAL_RCC_I2C1_CLK_ENABLE(); }while(0)      /* I2C1时钟使能 */
#define I2C1_I2C_CLK_DISABLE()          do{ __HAL_RCC_I2C1_CLK_DISABLE(); }while(0)     /* I2C1时钟失能 */

/* Exported variables (变量)---------------------------------------------------------*/

/* Exported functions (函数) ------------------------------------------------------- */

#define EE_TYPE AT24C04

void AT24CXX_Init(void);

void AT24CXX_Write(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite);

void AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead);

uint8_t AT24CXX_Check(void);
void AT24CXX_PAGE_Check(void);
#endif

24CXX.c文件代码如下:

nclude "./BSP/24CXX/24CXX.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
//初始化IIC接口
/* Exported constants (常量) --------------------------------------------------------*/

/* Exported macro (宏) --------------------------------------------------------------*/
#define AT24CXX_HANDLE  &g_iic_handler    /* IIC接口 */
#define AT24C_DEV_ADDR  0XA0              /* 设备地址 */
/* Exported variables (变量)---------------------------------------------------------*/
I2C_HandleTypeDef g_iic_handler;    /* I2C句柄 */
/* Exported functions (函数) ------------------------------------------------------- */

/*****************************************
函数名:void IIC_Init(void)
参数:无
功能描述:
返回值:无
*****************************************/
void IIC_Init(void)
{   
    g_iic_handler.Instance = I2C1_I2C;                              /* IIC1 */
    g_iic_handler.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;    /* 地址模式(7位) */
    g_iic_handler.Init.ClockSpeed        = 300000;                  /* 设置SCL时钟频率,该值要低于400k */
    g_iic_handler.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;   /* 不使用STM32的IIC设备地址2 */
    g_iic_handler.Init.DutyCycle        = I2C_DUTYCYCLE_2;          /* 时钟占空比即low/high = 2:1 或 16:9 */
    g_iic_handler.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;   /* IIC从模式时广播模式设置(主机模式时不使用) */
    g_iic_handler.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE;     /* IIC禁止时钟延长模式设置(从模式使用,主模式关闭) */
    g_iic_handler.Init.OwnAddress1     = 0x0A;                      /* STM32的IIC设备地址1(支持7bit或10bit) */
    g_iic_handler.Init.OwnAddress2     = 0;

    HAL_I2C_Init(&g_iic_handler);
}

/**
 * @brief       IIC底层驱动,时钟使能,引脚配置
 *   @note      此函数会被HAL_SPI_Init()调用
 * @param       hspi:SPI句柄
 * @retval      无
 */
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    /* I2C1 clock enable */
    I2C1_I2C_CLK_ENABLE();//放到了前面
    I2C1_SCL_GPIO_CLK_ENABLE();
          /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = I2C1_SCL_GPIO_PIN|I2C1_SDA_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;                     /*开漏输出模式*/
    GPIO_InitStruct.Pull = GPIO_NOPULL;                         /*不使用内部上拉或下拉电阻*/
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C1_SCL_GPIO_PORT, &GPIO_InitStruct);



    /* I2C1 interrupt Init */
//    HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0);
//    HAL_NVIC_EnableIRQ(I2C1_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }
}



void AT24CXX_Init(void)
{
    IIC_Init();//IIC初始化
    AT24CXX_Check();
}

/*****************************************
函数名:void AT24CXX_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite)
参数:WriteAddr :要写入数据的地址  DataToWrite:要写入的数据
功能描述:从指定地址开始写入1个字节数据
返回值:无
*****************************************/
void AT24CXX_WriteOneByte(uint16_t WriteAddr,uint8_t * DataToWrite)
{
#if USE_HARDWARE_IIC == 1
    uint8_t buf[2] = {WriteAddr>>8,WriteAddr%256};
    if(EE_TYPE>AT24C16)
    {
        if(HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR,WriteAddr,I2C_MEMADD_SIZE_8BIT,DataToWrite,1,HAL_MAX_DELAY) != HAL_OK)
        {
        
        }
    }
    else
    {
            if(EE_TYPE>AT24C16)
        {
            if(HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR,WriteAddr,I2C_MEMADD_SIZE_8BIT,DataToWrite,1,HAL_MAX_DELAY) != HAL_OK)
            {
            
            }
        }
        else
        if(HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR|((*buf& 0x07)<<1),*(buf+1),I2C_MEMADD_SIZE_8BIT,DataToWrite,1,HAL_MAX_DELAY) != HAL_OK)
        {
        
        }
    }
#else
  /* 根据不同的24CXX型号,发送高位地址
     * 1,24C16以上的型号,分2个字节发送地址
     * 2,24C16及以下的型号,发送1个低字节地址 + 占用器件地址的bit1~bit3位(用于表示高位地址,最多11位地址)
     *    对于24C01/02,其器件地址格式(8bit)为: 1 0 1 0 A2  A1 A0 R/W
     *    对于24C04,   其器件地址格式(8bit)为: 1 0 1 0 A2  A1 a8 R/W
     *    对于24C08,   其器件地址格式(8bit)为: 1 0 1 0 A2  a9 a8 R/W
     *    对于24C16,   其器件地址格式(8bit)为: 1 0 1 0 a10 a9 a8 R/W
     *    R/W      : 读/写控制位,0:写;1:读
     *    A0/A1/A2 : 对应器件的1/2/3引脚(只有24C01/02/04/08有这些脚)
     *    a8/a9/a10: 对应存储整列的高位地址,11bit地址最多可以表示2048个位置,可以寻址24C16及以内的型号
     */
    iic_start();                                    /* 产生IIC起始信号 */
    if (EE_TYPE > AT24C16)                          /* 24C16以上的型号,分2个字节发送地址 */
    {
        iic_send_byte(AT24C_DEV_ADDR);                        /* 发送写命令 */
        iic_wait_ack();                             /* 每发送完一个字节都要等待ACK */
        iic_send_byte(WriteAddr >> 8);                   /* 发送高字节地址 */
    }
    else                                            /* 24C16及以下的型号,发送1个低字节地址 + 占用器件地址的bit1~bit3位(用于表示高位地址,最多11位地址) */
    {
        iic_send_byte(AT24C_DEV_ADDR + ((WriteAddr >> 8) << 1));   /* 发送0xA0+高位a8/a9/a10地址,写命令 */
    }
    iic_wait_ack();                                 /* 每发送完一个字节都要等待ACK */
    iic_send_byte(WriteAddr % 256);                      /* 发送低位地址 */
    iic_wait_ack();
    
    iic_send_byte(WriteAddr);                            /* IIC发送一个字节 */
    iic_wait_ack();
    iic_stop();                                     /* 产生IIC停止信号 */
    HAL_Delay(10);                                   /* EEPROM的写入比较慢,必须等到10ms后再写下一个字节 */
#endif
}

/*****************************************
函数名:AT24CXX_WritePage(uint16_t WriteAddr,uint8_t u8Len, uint8_t *pData)
参数: WriteAddr : 要写入数据的地址  
            u8Len:要写入的数据
            pData:要写入的数据的首地址
功能描述:从指定地址开始写入1个字节数据
返回值:无
*****************************************/
void AT24CXX_WritePage(uint16_t WriteAddr,uint8_t u8Len, uint8_t *pData)
{
#if USE_HARDWARE_IIC == 1
    uint8_t buf[2] = {WriteAddr>>8,WriteAddr%256};
    
    if (u8Len > PAGE_SIZE)//长度大于页的长度
    {
        u8Len = PAGE_SIZE;
    }
    if ((WriteAddr + (uint16_t)u8Len) > CAPACITY_SIZE)//超过容量
    {
        u8Len = (uint8_t)(CAPACITY_SIZE - WriteAddr);
    }
    if (((WriteAddr % PAGE_SIZE) + (uint16_t)u8Len) > PAGE_SIZE)//判断是否跨页
    {
        u8Len -= (uint8_t)((WriteAddr + (uint16_t)u8Len) % PAGE_SIZE);//跨页,截掉跨页的部分
    }
    
    if(EE_TYPE>AT24C16)
    {
        if(HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR,WriteAddr,I2C_MEMADD_SIZE_8BIT,pData,u8Len,HAL_MAX_DELAY) != HAL_OK)
        {
        
        }
    }
    else
    {
        if(EE_TYPE<=AT24C02)
        {
        HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR,*(buf+1),I2C_MEMADD_SIZE_8BIT,pData,u8Len,HAL_MAX_DELAY);
        }
        else
        if(HAL_I2C_Mem_Write(AT24CXX_HANDLE,AT24C_DEV_ADDR|((*buf& 0x07)<<1),*(buf+1),I2C_MEMADD_SIZE_8BIT,pData,u8Len,HAL_MAX_DELAY) != HAL_OK)
        {
        
        }
    }
#endif
}
/*****************************************
函数名:uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
参数: ReadAddr:要读取数据的地址 pBuffer:回填数据首地址
功能描述:从指定地址开始读取1个字节数据
返回值:返回读取到的数据
*****************************************/
uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
{
#if USE_HARDWARE_IIC == 1
    uint8_t buf[2] = {ReadAddr>>8,ReadAddr%256},DataToRead = 0;
    if(EE_TYPE>AT24C16)
    {
        if(HAL_I2C_Master_Transmit(AT24CXX_HANDLE,AT24C_DEV_ADDR,buf,2,0xff) != HAL_OK)
        {
        
        }
    }else{
        if(HAL_I2C_Master_Transmit(AT24CXX_HANDLE,AT24C_DEV_ADDR|((*buf& 0x07)<<1),buf+1,1,0xff) != HAL_OK)
        {
        
        }
    }
    if(HAL_I2C_Master_Receive(AT24CXX_HANDLE,AT24C_DEV_ADDR|((*buf& 0x07)<<1),&DataToRead,1,0xff) != HAL_OK)
    {
    
    }
    return DataToRead;
#else
    uint8_t data;
    
    /* 根据不同的24CXX型号,发送高位地址
     * 1,24C16以上的型号,分2个字节发送地址
     * 2,24C16及以下的型号,发送1个低字节地址 + 占用器件地址的bit1~bit3位(用于表示高位地址,最多11位地址)
     *    对于24C01/02,其器件地址格式(8bit)为: 1 0 1 0 A2  A1 A0 R/W
     *    对于24C04,   其器件地址格式(8bit)为: 1 0 1 0 A2  A1 a8 R/W
     *    对于24C08,   其器件地址格式(8bit)为: 1 0 1 0 A2  a9 a8 R/W
     *    对于24C16,   其器件地址格式(8bit)为: 1 0 1 0 a10 a9 a8 R/W
     *    R/W      : 读/写控制位,0:写;1:读
     *    A0/A1/A2 : 对应器件的1/2/3引脚(只有24C01/02/04/08有这些脚)
     *    a8/a9/a10: 对应存储整列的高位地址,11bit地址最多可以表示2048个位置,可以寻址24C16及以内的型号
     */
    iic_start();                                    /* 产生IIC起始信号 */
    if (EE_TYPE > AT24C16)                          /* 24C16以上的型号,分2个字节发送地址 */
    {
        iic_send_byte(AT24C_DEV_ADDR);                        /* 发送写命令 */
        iic_wait_ack();                             /* 每发送完一个字节都要等待ACK */
        iic_send_byte(ReadAddr >> 8);                   /* 发送高字节地址 */
    }
    else                                            /* 24C16及以下的型号,发送1个低字节地址 + 占用器件地址的bit1~bit3位(用于表示高位地址,最多11位地址) */
    {
        iic_send_byte(AT24C_DEV_ADDR + ((ReadAddr >> 8) << 1));   /* 发送0xA0+高位a8/a9/a10地址,写命令 */
    }
    iic_wait_ack();                                 /* 每发送完一个字节都要等待ACK */
    iic_send_byte(ReadAddr % 256);                      /* 发送低位地址 */
    iic_wait_ack();
    
    iic_start();                                    /* 产生IIC起始信号 */
    iic_send_byte(AT24C_DEV_ADDR+1);                            /* 发送读命令 */
    iic_wait_ack();
    data = iic_read_byte(0);                        /* IIC读取一个字节 */
    iic_stop();                                     /* 产生IIC停止信号 */
    
    return data;
#endif
} 

/*****************************************
函数名:uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
参数: ReadAddr:要读取数据的地址 pBuffer:回填数据首地址
参数: WriteAddr : 读取的首地址
            u8Len:读取数据字节数,最大为CAPACITY_SIZE
            pBuff:读取数据存入的缓存
功能描述:从指定地址开始读取1个字节数据
返回值:返回读取到的数据
*****************************************/
void x24Cxx_ReadNByte(uint16_t ReadAddr, uint8_t *pBuff, uint16_t u16Len)
{
#if USE_HARDWARE_IIC == 1
    uint8_t buf[2] = {ReadAddr>>8,ReadAddr%256};
    if(EE_TYPE<=AT24C16)
    {//器件寻址+写+页选择位的处理
        if(EE_TYPE>AT24C02)
         buf[0]=AT24C_DEV_ADDR|((*buf& 0x07)<<1);
        else
         buf[0]=AT24C_DEV_ADDR;
    }
    
    if (u16Len > CAPACITY_SIZE)//读取长度大于存储器的总容量(字节)
        u16Len = CAPACITY_SIZE;
    if ((ReadAddr + (uint16_t)u16Len) > CAPACITY_SIZE)//超过容量,截掉超过的部分
        u16Len = (uint8_t)(CAPACITY_SIZE - ReadAddr);

    
    if(EE_TYPE>AT24C16)
    {
        if(HAL_I2C_Master_Transmit(AT24CXX_HANDLE,AT24C_DEV_ADDR,buf,2*u16Len,0xff) != HAL_OK)
        {
        
        }
    }else
    {
        if(HAL_I2C_Master_Transmit(AT24CXX_HANDLE,buf[0],buf+1,1,0xff) != HAL_OK)
        {
        
        }
    }
    if(HAL_I2C_Master_Receive(AT24CXX_HANDLE,buf[0],pBuff,u16Len,0xff) != HAL_OK)
    {
    
    }
#endif
}

/*****************************************
函数名:void AT24CXX_Write(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
参数:WriteAddr :要写入数据的地址  pBuffer:要写入的数据的首地址 NumToWrite:要写入数据的长度
功能描述:从指定地址开始写入多个字节数据
返回值:无
*****************************************/
void AT24CXX_Write(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
{
    uint8_t Fill_PAGE_SIZ,Number_PAGE_SIZ,Broken_PAGE_SIZ;
    Fill_PAGE_SIZ=PAGE_SIZE - (WriteAddr % PAGE_SIZE);                      //从写入地址开始填满一页所需的字节
    if(NumToWrite>Fill_PAGE_SIZ)
    Number_PAGE_SIZ=(NumToWrite-Fill_PAGE_SIZ)>>4;                          //需要填写的页数
    else
    Number_PAGE_SIZ=0;
    if(NumToWrite>Fill_PAGE_SIZ)                                            //最后不够一页的字节
    Broken_PAGE_SIZ=NumToWrite-Fill_PAGE_SIZ-Number_PAGE_SIZ*PAGE_SIZE;
    else
    Broken_PAGE_SIZ=0;
    
    if(NumToWrite>1)
    {
        if(NumToWrite>CAPACITY_SIZE)
            NumToWrite=CAPACITY_SIZE;
        if ((WriteAddr + (uint16_t)NumToWrite) > CAPACITY_SIZE)//超过容量
            {
            NumToWrite = (uint8_t)(CAPACITY_SIZE - WriteAddr);
            }
        if(NumToWrite>Fill_PAGE_SIZ)
        {
            AT24CXX_WritePage(WriteAddr,Fill_PAGE_SIZ,pBuffer);//从写的起始地址中写满一页
            WriteAddr+=Fill_PAGE_SIZ;
            pBuffer+=Fill_PAGE_SIZ;
            delay_ms(5);
            for(uint8_t i=0;i<Number_PAGE_SIZ;i++)//写完剩下的页数
                {
                AT24CXX_WritePage(WriteAddr,PAGE_SIZE,pBuffer);
                WriteAddr+=PAGE_SIZE;
                pBuffer+=PAGE_SIZE;
                delay_ms(5);
                }
            delay_ms(5);
            if(Broken_PAGE_SIZ!=0)
            AT24CXX_WritePage(WriteAddr,Broken_PAGE_SIZ,pBuffer);//写完剩下的不够一页的字节
        }
        else
        {
        AT24CXX_WritePage(WriteAddr,NumToWrite,pBuffer);//写完不够一页的字节
        }
//        AT24CXX_WritePage(WriteAddr,NumToWrite,pBuffer);
    }
    else
    {
        AT24CXX_WriteOneByte(WriteAddr,pBuffer);
        delay_ms(5);
    }
}

/*****************************************
函数名:AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
参数: ReadAddr:要读取数据的地址 pBuffer:回填数据首地址 NumToRead:数据长度
功能描述:从指定地址开始读取多个字节数据
返回值:无
*****************************************/
void AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
{
    if(NumToRead>1)
    {
        x24Cxx_ReadNByte(ReadAddr,pBuffer,NumToRead);
    }
    else
    {
        pBuffer[0] = AT24CXX_ReadOneByte(ReadAddr);
    }
} 
/*****************************************
函数名:uint8_t AT24CXX_Check(void)
参数:无
功能描述:检查AT24CXX是否正常,这里用了24XX的最后一个地址(255)来存储标志字.如果用其他24C系列,这个地址要修改
返回值:检测成功返回0 失败返回1
*****************************************/
uint8_t AT24CXX_Check(void)
{
    uint8_t temp;
    uint8_t data = 0XAC;
    AT24CXX_Read(EE_TYPE,&temp,1);//避免每次开机都写AT24CXX
    if(temp == 0XAC)
        return 0;
    AT24CXX_Write(EE_TYPE,&data,1);
    AT24CXX_Read(EE_TYPE,&temp,1);
    if(temp != 0XAC)
        return 1;
    return 0;
}
/*****************************************
函数名:void AT24CXX_PAGE_Check(void)
参数:     无
功能描述: 检查AT24CXX在页与页之间随机的任意地址写入任意长度的数据(数据长度不能超过存储容量)
返回值:    无
*****************************************/
void AT24CXX_PAGE_Check(void)
{   uint8_t judge=0XA5;
    uint8_t temp[40]={0};
    uint8_t data[PAGE_SIZE*2]={0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,\
                               0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC};
    //0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC,0XAC
    //0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5,0XA5

    AT24CXX_Write(0,data,5);
    delay_ms(5);
    printf("写入5个数据...\r\n"); 
    AT24CXX_Read(0,temp,5);
    if(temp[0] != judge)
    {
        printf("AT24CXX NG!\r\n");
    }
    else
    {
    printf("读取写入数据组1!\r\n"); 
    for(uint8_t i=0;i<sizeof(temp) / sizeof(temp[0]);i++)
        {
        printf("%#02X ",temp[i]);
        if(i>0&(i+1)%16==0)
            printf("\r\n");
        }
    }
    
    AT24CXX_Write(240,data,16);
    delay_ms(5);
    printf("\r\n写入16个数据...\r\n"); 
    AT24CXX_Read(240,temp,16);
    if(temp[0] != judge)
    {
        printf("AT24CXX NG!\r\n");
    }
    else
    {
    printf("读取写入数据组2!\r\n"); 
    for(uint8_t i=0;i<sizeof(temp) / sizeof(temp[0]);i++)
        {
        printf("%#02X ",temp[i]);
        if(i>0&(i+1)%16==0)
            printf("\r\n");
        }
    }
    
    AT24CXX_Write(240,data,20);
    delay_ms(5);
    printf("\r\n写入20个数据...\r\n"); 
    AT24CXX_Read(240,temp,20);
    if(temp[0] != judge)
    {
        printf("AT24CXX NG!\r\n");
    }
    else
    {
    printf("读取写入数据组3!\r\n"); 
    for(uint8_t i=0;i<sizeof(temp) / sizeof(temp[0]);i++)
        {
        printf("%#02X ",temp[i]);
        if(i>0&(i+1)%16==0)
            printf("\r\n");
        }
    }
    
    AT24CXX_Write(240,data,32);
    delay_ms(5);
    printf("\r\n写入32个数据...\r\n"); 
    AT24CXX_Read(240,temp,32);
    if(temp[0] != judge)
    {
        printf("AT24CXX NG!\r\n");
    }
    else
    {
    printf("读取写入数据组4!\r\n"); 
    for(uint8_t i=0;i<sizeof(temp) / sizeof(temp[0]);i++)
        {
        printf("%#02X ",temp[i]);
        if(i>0&(i+1)%16==0)
            printf("\r\n");
        }
    }
    
    AT24CXX_Write(245,data,32);
    delay_ms(5);
    printf("\r\n偏移5个地址写入32个数据...\r\n"); 
    AT24CXX_Read(245,temp,32);
    if(temp[0] != judge)
    {
        printf("AT24CXX NG!\r\n");
    }
    else
    {
    printf("读取写入数据组5!\r\n"); 
    for(uint8_t i=0;i<sizeof(temp) / sizeof(temp[0]);i++)
        {
        printf("%#02X ",temp[i]);
        if(i>0&(i+1)%16==0)
            printf("\r\n");
        }
    }
    
}

作者:qq_3227305

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 (基于HAL库) 硬件IIC任意地址读写任意字节—-AT24CXX芯片

发表回复