基于野火STM32F103ZET6开发板 I2C读写EEPROM学习

前言

本文主要记录自己在使用野火STM32F103ZET6开发板学习I2c读写EEPROM的学习过程

导语

好记性不如烂笔头,做技术要沉下心,相信每次阅读源码都会有不同的收获

一、什么是EEPROM

EEPROM(Electrically Erasable Programmable ROM)是电可擦除存储器。EEPROM可以重复擦写,它的擦除和写入都是直接使用电路控制,不需要再使用外部设备来擦写。而且可以按字节为单位修改数据,无需整个芯片擦除。现在主要使用的ROM芯片都是EEPROM。

1.1 AT24C02 EEPROM介绍

开发板上使用的EEPROM IC芯片型号为AT24C02,存储容量为2K bit,内容被分成32页,每页8Bytes,共256Bytes
在这里插入图片描述

1.2 AT24C02 pin介绍

AT24C02芯片通信方式为I2C(SCL/SDA),具备写保护(WP),地址可配(A0/A1/A2)最多可级联8个器件(000-111)。
在这里插入图片描述

1.3 AT24C02芯片寻址

芯片寻址:AT24C02的芯片地址为1010,其地址控制字格式为1010A2A1A0R/W。其中A2,A1,A0可编程地址选择位。A2,A1,A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该器件的地址码。R/W为芯片读写控制位,该位为0,表示芯片进行写操作。
片内子地址寻址:芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。
在这里插入图片描述

二、stm32驱动EEPROM

2.1 确认和EEPROM的连接管脚

在码代码之前首先需要查看原理图确认EEPROM连接在了stm32上的那一路i2c上,由原理图可知,EEPROM通过PB6和PB7连接到了stm32,并且A0/A1/A2地址线全部拉低,所以该芯片的I2c slave 7bit地址为1010000b,后面我们编程会用到。
在这里插入图片描述

2.2 使用stm32cubemx配置I2C1

使用stm32cubemx快速配置I2C1,7bit slave,标准模式,100Khz,如下
在这里插入图片描述

2.3 读写接口代码详解

AT24C02的i2c驱动代码采用github开源代码,详见链接:
https://github.com/hepingood/at24cxx/tree/master,
虽然是一个简单的i2c驱动读写,但是代码写的很好,尤其是设计的框架,移植到mcu上或是linux上都挺好用,正好用来学习(移植适配底层I2C读写接口就行)
driver_at24xx.h

/**
 * Copyright (c) 2015 - present LibDriver All rights reserved
 * 
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 *
 * @file      driver_at24cxx.h
 * @brief     driver at24cxx header file
 * @version   2.0.0
 * @author    Shifeng Li
 * @date      2021-02-17
 *
 * <h3>history</h3>
 * <table>
 * <tr><th>Date        <th>Version  <th>Author      <th>Description
 * <tr><td>2021/02/17  <td>2.0      <td>Shifeng Li  <td>format the code
 * <tr><td>2020/10/15  <td>1.0      <td>Shifeng Li  <td>first upload
 * </table>
 */

#ifndef DRIVER_AT24CXX_H
#define DRIVER_AT24CXX_H

#include <stdio.h>
#include <stdint.h>
#include <string.h>

#ifdef __cplusplus
extern "C"{
#endif

/**
 * @defgroup at24cxx_driver at24cxx driver function
 * @brief    at24cxx driver modules
 * @{
 */

/**
 * @addtogroup at24cxx_base_driver
 * @{
 */

/**
 * @brief at24cxx type enumeration definition
 */
typedef enum
{
    AT24C01  = 128,          /**< AT24C01 type */
    AT24C02  = 256,          /**< AT24C02 type */
    AT24C04  = 512,          /**< AT24C04 type */
    AT24C08  = 1024,         /**< AT24C08 type */
    AT24C16  = 2048,         /**< AT24C16 type */
    AT24C32  = 4096,         /**< AT24C32 type */
    AT24C64  = 8192,         /**< AT24C64 type */
    AT24C128 = 16384,        /**< AT24C128 type */
    AT24C256 = 32768,        /**< AT24C256 type */
} at24cxx_t;

/**
 * @brief at24cxx address enumeration definition
 */
typedef enum
{
    AT24CXX_ADDRESS_A000 = 0,        /**< A2A1A0 000 */
    AT24CXX_ADDRESS_A001 = 1,        /**< A2A1A0 001 */
    AT24CXX_ADDRESS_A010 = 2,        /**< A2A1A0 010 */
    AT24CXX_ADDRESS_A011 = 3,        /**< A2A1A0 011 */
    AT24CXX_ADDRESS_A100 = 4,        /**< A2A1A0 100 */
    AT24CXX_ADDRESS_A101 = 5,        /**< A2A1A0 101 */
    AT24CXX_ADDRESS_A110 = 6,        /**< A2A1A0 110 */
    AT24CXX_ADDRESS_A111 = 7,        /**< A2A1A0 111 */
} at24cxx_address_t;

/**
 * @brief at24cxx handle structure definition
 */
typedef struct at24cxx_handle_s
{
    uint8_t iic_addr;                                                                              /**< iic device address */
    uint8_t (*iic_init)(void);                                                                     /**< point to an iic_init function address */
    uint8_t (*iic_deinit)(void);                                                                   /**< point to an iic_deinit function address */
    uint8_t (*iic_read)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len);                    /**< point to an iic_read function address */
    uint8_t (*iic_write)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len);                   /**< point to an iic_write function address */
    uint8_t (*iic_read_address16)(uint8_t addr, uint16_t reg, uint8_t *buf, uint16_t len);         /**< point to an iic_read_address16 function address */
    uint8_t (*iic_write_address16)(uint8_t addr, uint16_t reg, uint8_t *buf, uint16_t len);        /**< point to an iic_write_address16 function address */
    void (*delay_ms)(uint32_t ms);                                                                 /**< point to a delay_ms function address */
    void (*debug_print)(const char *const fmt, ...);                                               /**< point to a debug_print function address */
    uint16_t id;                                                                                   /**< chip id */
    uint8_t inited;                                                                                /**< inited flag */
} at24cxx_handle_t;

/**
 * @brief at24cxx information structure definition
 */
typedef struct at24cxx_info_s
{
    char chip_name[32];                /**< chip name */
    char manufacturer_name[32];        /**< manufacturer name */
    char interface[8];                 /**< chip interface name */
    float supply_voltage_min_v;        /**< chip min supply voltage */
    float supply_voltage_max_v;        /**< chip max supply voltage */
    float max_current_ma;              /**< chip max current */
    float temperature_min;             /**< chip min operating temperature */
    float temperature_max;             /**< chip max operating temperature */
    uint32_t driver_version;           /**< driver version */
} at24cxx_info_t;

/**
 * @}
 */

/**
 * @defgroup at24cxx_link_driver at24cxx link driver function
 * @brief    at24cxx link driver modules
 * @ingroup  at24cxx_driver
 * @{
 */

/**
 * @brief     initialize at24cxx_handle_t structure
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] STRUCTURE is at24cxx_handle_t
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_INIT(HANDLE, STRUCTURE)           memset(HANDLE, 0, sizeof(STRUCTURE))

/**
 * @brief     link iic_init function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_init function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_INIT(HANDLE, FUC)             (HANDLE)->iic_init = FUC

/**
 * @brief     link iic_deinit function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_deinit function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_DEINIT(HANDLE, FUC)           (HANDLE)->iic_deinit = FUC

/**
 * @brief     link iic_read function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_read function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_READ(HANDLE, FUC)             (HANDLE)->iic_read = FUC

/**
 * @brief     link iic_write function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_write function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_WRITE(HANDLE, FUC)            (HANDLE)->iic_write = FUC

/**
 * @brief     link iic_read_address16 function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_read_address16 function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_READ_ADDRESS16(HANDLE, FUC)   (HANDLE)->iic_read_address16 = FUC

/**
 * @brief     link iic_write_address16 function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to an iic_write_address16 function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_IIC_WRITE_ADDRESS16(HANDLE, FUC)  (HANDLE)->iic_write_address16 = FUC

/**
 * @brief     link delay_ms function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to a delay_ms function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_DELAY_MS(HANDLE, FUC)             (HANDLE)->delay_ms = FUC

/**
 * @brief     link debug_print function
 * @param[in] HANDLE points to an at24cxx handle structure
 * @param[in] FUC points to a debug_print function address
 * @note      none
 */
#define DRIVER_AT24CXX_LINK_DEBUG_PRINT(HANDLE, FUC)          (HANDLE)->debug_print = FUC

/**
 * @}
 */

/**
 * @defgroup at24cxx_base_driver at24cxx base driver function
 * @brief    at24cxx base driver modules
 * @ingroup  at24cxx_driver
 * @{
 */

/**
 * @brief      get chip's information
 * @param[out] *info points to an at24cxx info structure
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_info(at24cxx_info_t *info);

/**
 * @brief     initialize the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @return    status code
 *            - 0 success
 *            - 1 iic initialization failed
 *            - 2 handle is NULL
 *            - 3 linked functions is NULL
 * @note      none
 */
uint8_t at24cxx_init(at24cxx_handle_t *handle);

/**
 * @brief     close the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @return    status code
 *            - 0 success
 *            - 1 iic deinit failed
 *            - 2 handle is NULL
 *            - 3 handle is not initialized
 * @note      none
 */
uint8_t at24cxx_deinit(at24cxx_handle_t *handle);

/**
 * @brief     set the chip type
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] type is the chip type
 * @return    status code
 *            - 0 success
 *            - 2 handle is NULL
 * @note      none
 */
uint8_t at24cxx_set_type(at24cxx_handle_t *handle, at24cxx_t type);

/**
 * @brief      get the chip type
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[out] *type points to a chip type buffer
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_get_type(at24cxx_handle_t *handle, at24cxx_t *type);

/**
 * @brief     set the chip address pin
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] addr_pin is the chip address pin
 * @return    status code
 *            - 0 success
 *            - 2 handle is NULL
 * @note      none
 */
uint8_t at24cxx_set_addr_pin(at24cxx_handle_t *handle, at24cxx_address_t addr_pin);

/**
 * @brief      get the chip address pin
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[out] *addr_pin points to a chip address pin
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_get_addr_pin(at24cxx_handle_t *handle, at24cxx_address_t *addr_pin);

/**
 * @brief      read bytes from the chip
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[in]  address is the register address
 * @param[out] *buf points to a data buffer
 * @param[in]  len is the buffer length
 * @return     status code
 *             - 0 success
 *             - 1 read data failed
 *             - 2 handle is NULL
 *             - 3 handle is not initialized
 *             - 4 end address is over the max address
 * @note       none
 */
uint8_t at24cxx_read(at24cxx_handle_t *handle, uint16_t address, uint8_t *buf, uint16_t len);

/**
 * @brief     write bytes to the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] address is the register address
 * @param[in] *buf points to a data buffer
 * @param[in] len is the buffer length
 * @return    status code
 *            - 0 success
 *            - 1 write data failed
 *            - 2 handle is NULL
 *            - 3 handle is not initialized
 *            - 4 end address is over the max address
 * @note      none
 */
uint8_t at24cxx_write(at24cxx_handle_t *handle, uint16_t address, uint8_t *buf, uint16_t len);

/**
 * @}
 */

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif

driver_at24cxx.c

/**
 * Copyright (c) 2015 - present LibDriver All rights reserved
 * 
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 *
 * @file      driver_at24cxx.c
 * @brief     driver at24cxx source file
 * @version   2.0.0
 * @author    Shifeng Li
 * @date      2021-02-17
 *
 * <h3>history</h3>
 * <table>
 * <tr><th>Date        <th>Version  <th>Author      <th>Description
 * <tr><td>2021/02/17  <td>2.0      <td>Shifeng Li  <td>format the code
 * <tr><td>2020/10/15  <td>1.0      <td>Shifeng Li  <td>first upload
 * </table>
 */

#include "driver_at24cxx.h"

/**
 * @brief chip information definition
 */
#define CHIP_NAME                 "Microchip AT24CXX"       /**< chip name */
#define MANUFACTURER_NAME         "Microchip"               /**< manufacturer name */
#define SUPPLY_VOLTAGE_MIN        1.7f                      /**< chip min supply voltage */
#define SUPPLY_VOLTAGE_MAX        5.5f                      /**< chip max supply voltage */
#define MAX_CURRENT               5.0f                      /**< chip max current */
#define TEMPERATURE_MIN           -40.0f                    /**< chip min operating temperature */
#define TEMPERATURE_MAX           85.0f                     /**< chip max operating temperature */
#define DRIVER_VERSION            2000                      /**< driver version */

/**
 * @brief     initialize the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @return    status code
 *            - 0 success
 *            - 1 iic initialization failed
 *            - 2 handle is NULL
 *            - 3 linked functions is NULL
 * @note      none
 */
uint8_t at24cxx_init(at24cxx_handle_t *handle)
{
    if (handle == NULL)                                                        /* check handle */
    {
        return 2;                                                              /* return error */
    }
    if (handle->debug_print == NULL)                                           /* check debug_print */
    {
        return 3;                                                              /* return error */
    }
    if (handle->iic_init == NULL)                                              /* check iic_init */
    {
        handle->debug_print("at24cxx: iic_init is null.\n");                   /* iic_init is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->iic_deinit == NULL)                                            /* check iic_deinit */
    {
        handle->debug_print("at24cxx: iic_deinit is null.\n");                 /* iic_deinit is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->iic_read == NULL)                                              /* check iic_read */
    {
        handle->debug_print("at24cxx: iic_read is null.\n");                   /* iic_read is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->iic_write == NULL)                                             /* check iic_write */
    {
        handle->debug_print("at24cxx: iic_write is null.\n");                  /* iic_write is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->iic_read_address16 == NULL)                                    /* check iic_read_address16 */
    {
        handle->debug_print("at24cxx: iic_read_address16 is null.\n");         /* iic_read_address16 is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->iic_write_address16 == NULL)                                   /* check iic_write_address16 */
    {
        handle->debug_print("at24cxx: iic_write_address16 is null.\n");        /* iic_write_address16 is null */
       
        return 3;                                                              /* return error */
    }
    if (handle->delay_ms == NULL)                                              /* check delay_ms */
    {
        handle->debug_print("at24cxx: delay_ms is null.\n");                   /* delay_ms is null */
       
        return 3;                                                              /* return error */
    }

    if (handle->iic_init() != 0)                                               /* iic init */
    {
        handle->debug_print("at24cxx: iic init failed.\n");                    /* iic init failed */
       
        return 1;                                                              /* return error */
    }
    handle->inited = 1;                                                        /* flag finish initialization */

    return 0;                                                                  /* success return 0 */
}

/**
 * @brief     close the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @return    status code
 *            - 0 success
 *            - 1 iic deinit failed
 *            - 2 handle is NULL
 *            - 3 handle is not initialized
 * @note      none
 */
uint8_t at24cxx_deinit(at24cxx_handle_t *handle)
{
    if (handle == NULL)                                              /* check handle */
    {
        return 2;                                                    /* return error */
    }
    if (handle->inited != 1)                                         /* check handle initialization */
    {
        return 3;                                                    /* return error */
    }
    
    if (handle->iic_deinit() != 0)                                   /* iic deinit */
    {
        handle->debug_print("at24cxx: iic deinit failed.\n");        /* iic deinit failed */
        
        return 1;                                                    /* return error */
    }   
    handle->inited = 0;                                              /* flag close */
    
    return 0;                                                        /* success return 0 */
}

/**
 * @brief     set the chip type
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] type is the chip type
 * @return    status code
 *            - 0 success
 *            - 2 handle is NULL
 * @note      none
 */
uint8_t at24cxx_set_type(at24cxx_handle_t *handle, at24cxx_t type)
{
    if (handle == NULL)                 /* check handle */
    {
        return 2;                       /* return error */
    }

    handle->id = (uint16_t)type;        /* set id */
    
    return 0;                           /* success return 0 */
}

/**
 * @brief      get the chip type
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[out] *type points to a chip type buffer
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_get_type(at24cxx_handle_t *handle, at24cxx_t *type)
{
    if (handle == NULL)                     /* check handle */
    {
        return 2;                           /* return error */
    }

    *type = (at24cxx_t)(handle->id);        /* get id */
    
    return 0;                               /* success return 0 */
}

/**
 * @brief     set the chip address pin
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] addr_pin is the chip address pin
 * @return    status code
 *            - 0 success
 *            - 2 handle is NULL
 * @note      none
 */
uint8_t at24cxx_set_addr_pin(at24cxx_handle_t *handle, at24cxx_address_t addr_pin)
{
    if (handle == NULL)                       /* check handle */
    {
        return 2;                             /* return error */
    }

    handle->iic_addr = 0xA0;                  /* set iic addr */
    handle->iic_addr |= addr_pin << 1;        /* set iic address */
    
    return 0;                                 /* success return 0 */
}

/**
 * @brief      get the chip address pin
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[out] *addr_pin points to a chip address pin
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_get_addr_pin(at24cxx_handle_t *handle, at24cxx_address_t *addr_pin)
{
    if (handle == NULL)                                                        /* check handle */
    {
        return 2;                                                              /* return error */
    }

    *addr_pin = (at24cxx_address_t)((handle->iic_addr & (~0xA0)) >> 1);        /* get iic address */
    
    return 0;                                                                  /* success return 0 */
}

/**
 * @brief      read bytes from the chip
 * @param[in]  *handle points to an at24cxx handle structure
 * @param[in]  address is the register address
 * @param[out] *buf points to a data buffer
 * @param[in]  len is the buffer length
 * @return     status code
 *             - 0 success
 *             - 1 read data failed
 *             - 2 handle is NULL
 *             - 3 handle is not initialized
 *             - 4 end address is over the max address
 * @note       none
 */
uint8_t at24cxx_read(at24cxx_handle_t *handle, uint16_t address, uint8_t *buf, uint16_t len)
{
    uint8_t page_remain;
    
    if (handle == NULL)                                                                                      /* check handle */
    {
        return 2;                                                                                            /* return error */
    }
    if (handle->inited != 1)                                                                                 /* check handle initialization */
    {
        return 3;                                                                                            /* return error */
    }

    if ((address + len) > handle->id)                                                                        /* check length */
    {
        handle->debug_print("at24cxx: read out of range.\n");                                                /* read out of range */
       
        return 4;                                                                                            /* return error */
    }
    page_remain = (uint8_t)(8 - address % 8);                                                                /* get page remain */
    if (len <= page_remain)                                                                                  /* page remain */
    {
        page_remain = (uint8_t)len;                                                                          /* set page remain */
    }
    if (handle->id > (uint16_t)AT24C16)                                                                      /* choose id to set different address */
    {
        while (1)
        {
            if (handle->iic_read_address16(handle->iic_addr, address, buf, page_remain) != 0)                /* read data */
            {
                handle->debug_print("at24cxx: read failed.\n");                                              /* read failed */
               
                return 1;                                                                                    /* return error */
            }
            if (page_remain == len)                                                                          /* check break */
            {
                break;                                                                                       /* break loop */
            }
            else
            {
                address += page_remain;                                                                      /* address increase */
                buf += page_remain;                                                                          /* buffer point increase */
                len -= page_remain;                                                                          /* length decrease */
                if (len < 8)                                                                                 /* check length */
                {
                    page_remain = (uint8_t)len;                                                              /* set the reset length */
                }
                else
                {
                    page_remain = 8;                                                                         /* set page */
                }
            }
        }
    }
    else
    {
        while (1)
        {
            if (handle->iic_read((uint8_t)(handle->iic_addr + ((address / 256) << 1)), address % 256, buf,
                                  page_remain) != 0)                                                         /* read page */
            {
                handle->debug_print("at24cxx: read failed.\n");                                              /* read failed */
               
                return 1;                                                                                    /* return error */
            }
            if (page_remain == len)                                                                          /* check break */
            {
                break;                                                                                       /* break loop */
            }
            else
            {
                address += page_remain;                                                                      /* address increase */
                buf += page_remain;                                                                          /* buffer point increase */
                len -= page_remain;                                                                          /* length decrease */
                if (len < 8)                                                                                 /* check length */
                {
                    page_remain = (uint8_t)len;                                                              /* set the reset length */
                }
                else
                {
                    page_remain = 8;                                                                         /* set page */
                }
            }
        }
    }
    
    return 0;                                                                                                /* success return 0 */
}

/**
 * @brief     write bytes to the chip
 * @param[in] *handle points to an at24cxx handle structure
 * @param[in] address is the register address
 * @param[in] *buf points to a data buffer
 * @param[in] len is the buffer length
 * @return    status code
 *            - 0 success
 *            - 1 write data failed
 *            - 2 handle is NULL
 *            - 3 handle is not initialized
 *            - 4 end address is over the max address
 * @note      none
 */
uint8_t at24cxx_write(at24cxx_handle_t *handle, uint16_t address, uint8_t *buf, uint16_t len)
{
    uint8_t page_remain;
    
    if (handle == NULL)                                                                                       /* check handle */
    {
        return 2;                                                                                             /* return error */
    }
    if (handle->inited != 1)                                                                                  /* check handle initialization */
    {
        return 3;                                                                                             /* return error */
    }

    if ((address + len) > handle->id)                                                                         /* check length */
    {
        handle->debug_print("at24cxx: write out of range.\n");                                                /* write out of range */
       
        return 1;                                                                                             /* return error */
    }
    page_remain = (uint8_t)(8 - address % 8);                                                                 /* set page remain */
    if (len <= page_remain)                                                                                   /* check length */
    {
        page_remain = (uint8_t)len;                                                                           /* set page remain */
    }
    if (handle->id > (uint16_t)AT24C16)                                                                       /* check id */
    {
        while (1)
        {
            if (handle->iic_write_address16(handle->iic_addr, address, buf, page_remain) != 0)                /* write data */
            {
                handle->debug_print("at24cxx: write failed.\n");                                              /* write failed */
               
                return 1;                                                                                     /* return error */
            }
            handle->delay_ms(6);                                                                              /* wait 6 ms */
            if (page_remain == len)                                                                           /* check break */
            {
                break;                                                                                        /* break */
            }
            else
            {
                address += page_remain;                                                                       /* address increase */
                buf += page_remain;                                                                           /* buffer point increase */
                len -= page_remain;                                                                           /* length decrease */
                if (len < 8)                                                                                  /* check length */
                {
                    page_remain = (uint8_t)len;                                                               /* set the reset length */
                }
                else
                {
                    page_remain = 8;                                                                          /* set page */
                }
            }
        }
    }        
    else
    {
        while (1)
        {
            if (handle->iic_write((uint8_t)(handle->iic_addr + ((address / 256) << 1)), address % 256, buf,
                                  page_remain) != 0)                                                          /* write page */
            {
                handle->debug_print("at24cxx: write failed.\n");                                              /* write failed */
               
                return 1;                                                                                     /* return error */
            }
            handle->delay_ms(6);                                                                              /* wait 6 ms */
            if (page_remain == len)                                                                           /* check break */
            {
                break;                                                                                        /* break */
            }
            else
            {
                address += page_remain;                                                                       /* address increase */
                buf += page_remain;                                                                           /* buffer point increase */
                len -= page_remain;                                                                           /* length decrease */
                if (len < 8)                                                                                  /* check length */
                {
                    page_remain = (uint8_t)len;                                                               /* set the rest length */
                }
                else
                {
                    page_remain = 8;                                                                          /* set page */
                }
            }
        }
    }
    
    return 0;                                                                                                 /* success return 0 */
}

/**
 * @brief      get chip's information
 * @param[out] *info points to an at24cxx info structure
 * @return     status code
 *             - 0 success
 *             - 2 handle is NULL
 * @note       none
 */
uint8_t at24cxx_info(at24cxx_info_t *info)
{
    if (info == NULL)                                               /* check handle */
    {
        return 2;                                                   /* return error */
    }
    
    memset(info, 0, sizeof(at24cxx_info_t));                        /* initialize at24cxx info structure */
    strncpy(info->chip_name, CHIP_NAME, 32);                        /* copy chip name */
    strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32);        /* copy manufacturer name */
    strncpy(info->interface, "IIC", 8);                             /* copy interface name */
    info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN;                /* set minimal supply voltage */
    info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX;                /* set maximum supply voltage */
    info->max_current_ma = MAX_CURRENT;                             /* set maximum current */
    info->temperature_max = TEMPERATURE_MAX;                        /* set minimal temperature */
    info->temperature_min = TEMPERATURE_MIN;                        /* set maximum temperature */
    info->driver_version = DRIVER_VERSION;                          /* set driver version */
    
    return 0;                                                       /* success return 0 */
}


//待更新详细代码分析

引用

  1. 《常见存储器介绍》https://doc.embedfire.com/mcu/stm32/f103/hal_general/zh/latest/doc/chapter22/chapter22.html
  2. 《I2C-读写EEPROM》
    https://doc.embedfire.com/mcu/stm32/f103/hal_general/zh/latest/doc/chapter23/chapter23.html
  3. 《AT24C02芯片手册》
  4. 《百度百科AT24C02》
    https://baike.baidu.com/item/AT24C02/5665387?fr=ge_ala
  5. github开源AT24XX驱动
    https://github.com/hepingood/at24cxx/tree/master
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值