目录
前言
本文主要记录自己在使用野火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 */
}
//待更新详细代码分析
引用
- 《常见存储器介绍》https://doc.embedfire.com/mcu/stm32/f103/hal_general/zh/latest/doc/chapter22/chapter22.html
- 《I2C-读写EEPROM》
https://doc.embedfire.com/mcu/stm32/f103/hal_general/zh/latest/doc/chapter23/chapter23.html - 《AT24C02芯片手册》
- 《百度百科AT24C02》
https://baike.baidu.com/item/AT24C02/5665387?fr=ge_ala - github开源AT24XX驱动
https://github.com/hepingood/at24cxx/tree/master