重构为初始化传入读写延时函数的接口
This commit is contained in:
60
README.md
60
README.md
@@ -6,65 +6,51 @@
|
|||||||
|
|
||||||
- 不依赖特定 MCU/SDK(不绑定 STM32 HAL)
|
- 不依赖特定 MCU/SDK(不绑定 STM32 HAL)
|
||||||
- 支持页写自动拆分
|
- 支持页写自动拆分
|
||||||
- 通过回调适配底层总线
|
- 用户传入 I2C 读、I2C 写、毫秒延时三个函数后即可直接使用
|
||||||
|
|
||||||
## 目录结构
|
## 目录结构
|
||||||
|
|
||||||
- `module/Int_EEPROM24xx.h`:驱动接口定义
|
- `module/Int_EEPROM24xx.h`:驱动接口
|
||||||
- `module/Int_EEPROM24xx.c`:驱动实现
|
- `module/Int_EEPROM24xx.c`:驱动实现
|
||||||
- `examples/adapter_template.c`:适配层模板
|
- `examples/adapter_template.c`:移植模板
|
||||||
|
|
||||||
## 你需要实现的 3 个函数
|
## 使用步骤
|
||||||
|
|
||||||
移植时,你只需要实现这三个底层函数,然后在配置结构体里挂接:
|
1. 将 `module/Int_EEPROM24xx.h/.c` 加入你的工程。
|
||||||
|
2. 在你的平台实现三个函数:
|
||||||
|
- `your_i2c_read(...)`
|
||||||
|
- `your_i2c_write(...)`
|
||||||
|
- `your_delay_ms(...)`
|
||||||
|
3. 调用 `Int_EEPROM24xx_Init(...)` 完成初始化。
|
||||||
|
4. 直接调用 `Int_EEPROM24xx_Read/Write` 进行访问。
|
||||||
|
|
||||||
1. `bus_read`:从 EEPROM 读数据
|
## 示例
|
||||||
2. `bus_write`:向 EEPROM 写数据
|
|
||||||
3. `delay_ms`:毫秒延时
|
|
||||||
|
|
||||||
> 这也是本仓库提交信息里的重点:**需要自己实现读、写、延时这三个函数**。
|
|
||||||
|
|
||||||
## 快速接入
|
|
||||||
|
|
||||||
### 1) 将模块加入工程
|
|
||||||
|
|
||||||
把以下文件加入你的工程:
|
|
||||||
|
|
||||||
- `module/Int_EEPROM24xx.h`
|
|
||||||
- `module/Int_EEPROM24xx.c`
|
|
||||||
|
|
||||||
### 2) 实现底层适配函数
|
|
||||||
|
|
||||||
参考 `examples/adapter_template.c`,按你的平台替换 I2C 读写与延时实现。
|
|
||||||
|
|
||||||
### 3) 初始化设备描述并调用 API
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
static const IntEEPROM24xx_t g_eeprom = {
|
IntEEPROM24xx_Config_t cfg = {
|
||||||
.ctx = your_bus_context,
|
|
||||||
.dev_addr = (0x50u << 1),
|
.dev_addr = (0x50u << 1),
|
||||||
.page_size = 8u,
|
.page_size = 8u,
|
||||||
.mem_addr_size = 1u,
|
.mem_addr_size = 1u,
|
||||||
.write_cycle_ms = 6u,
|
.write_cycle_ms = 6u,
|
||||||
.timeout_ms = 100u,
|
.timeout_ms = 100u,
|
||||||
.bus_read = your_bus_read,
|
|
||||||
.bus_write = your_bus_write,
|
|
||||||
.delay_ms = your_delay_ms,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Int_EEPROM24xx_Read(&g_eeprom, 0x00, rx_buf, sizeof(rx_buf));
|
Int_EEPROM24xx_Init(&cfg, your_i2c_read, your_i2c_write, your_delay_ms);
|
||||||
Int_EEPROM24xx_Write(&g_eeprom, 0x00, tx_buf, sizeof(tx_buf));
|
|
||||||
|
Int_EEPROM24xx_Write(0x00, tx_buf, tx_len);
|
||||||
|
Int_EEPROM24xx_Read(0x00, rx_buf, rx_len);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 参数说明
|
## 参数说明
|
||||||
|
|
||||||
- `dev_addr`:设备地址(7bit 或左移后地址,取决于你的底层驱动规范)
|
- `dev_addr`:设备地址(7bit 或左移后地址,取决于底层驱动规范)
|
||||||
- `page_size`:页大小(必须与芯片手册一致)
|
- `page_size`:页大小(必须与芯片手册一致)
|
||||||
- `mem_addr_size`:地址字节数(1 或 2)
|
- `mem_addr_size`:地址字节数(1 或 2)
|
||||||
- `write_cycle_ms`:每次页写后的写周期等待
|
- `write_cycle_ms`:每次页写后的写周期等待
|
||||||
|
- `timeout_ms`:底层总线访问超时
|
||||||
|
|
||||||
## 常见问题
|
## 注意事项
|
||||||
|
|
||||||
- 写入失败:优先检查 `page_size` 和 `write_cycle_ms`
|
- 驱动内部会自动按页拆分写入,避免跨页写异常。
|
||||||
- 读写偏移错乱:检查 `mem_addr_size`(1 字节 / 2 字节)
|
- 若你的器件使用 2 字节地址,请设置 `mem_addr_size = 2`。
|
||||||
- 跨平台报错:说明底层回调未按目标 SDK 正确实现。
|
- 若写后立即读失败,请适当增大 `write_cycle_ms`。
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
#include "Int_EEPROM24xx.h"
|
#include "Int_EEPROM24xx.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 这是移植模板:请把这 3 个函数替换为你的平台实现。
|
* 移植模板:你只需要实现这 3 个函数。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static IntEEPROM_Result_t your_bus_read(void *ctx,
|
static IntEEPROM_Result_t your_i2c_read(uint16_t dev_addr,
|
||||||
uint16_t dev_addr,
|
|
||||||
uint32_t mem_addr,
|
uint32_t mem_addr,
|
||||||
uint8_t mem_addr_size,
|
uint8_t mem_addr_size,
|
||||||
uint8_t *buf,
|
uint8_t *buf,
|
||||||
uint16_t len,
|
uint16_t len,
|
||||||
uint32_t timeout_ms)
|
uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
(void)ctx;
|
|
||||||
(void)dev_addr;
|
(void)dev_addr;
|
||||||
(void)mem_addr;
|
(void)mem_addr;
|
||||||
(void)mem_addr_size;
|
(void)mem_addr_size;
|
||||||
@@ -20,19 +18,17 @@ static IntEEPROM_Result_t your_bus_read(void *ctx,
|
|||||||
(void)len;
|
(void)len;
|
||||||
(void)timeout_ms;
|
(void)timeout_ms;
|
||||||
|
|
||||||
/* TODO: 替换为平台 I2C 读函数 */
|
/* TODO: 替换为你的平台 I2C 读实现 */
|
||||||
return INT_EEPROM_ERR_IO;
|
return INT_EEPROM_ERR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntEEPROM_Result_t your_bus_write(void *ctx,
|
static IntEEPROM_Result_t your_i2c_write(uint16_t dev_addr,
|
||||||
uint16_t dev_addr,
|
|
||||||
uint32_t mem_addr,
|
uint32_t mem_addr,
|
||||||
uint8_t mem_addr_size,
|
uint8_t mem_addr_size,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
uint16_t len,
|
uint16_t len,
|
||||||
uint32_t timeout_ms)
|
uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
(void)ctx;
|
|
||||||
(void)dev_addr;
|
(void)dev_addr;
|
||||||
(void)mem_addr;
|
(void)mem_addr;
|
||||||
(void)mem_addr_size;
|
(void)mem_addr_size;
|
||||||
@@ -40,36 +36,34 @@ static IntEEPROM_Result_t your_bus_write(void *ctx,
|
|||||||
(void)len;
|
(void)len;
|
||||||
(void)timeout_ms;
|
(void)timeout_ms;
|
||||||
|
|
||||||
/* TODO: 替换为平台 I2C 写函数 */
|
/* TODO: 替换为你的平台 I2C 写实现 */
|
||||||
return INT_EEPROM_ERR_IO;
|
return INT_EEPROM_ERR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void your_delay_ms(void *ctx, uint32_t delay_ms)
|
static void your_delay_ms(uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
(void)ctx;
|
|
||||||
(void)delay_ms;
|
(void)delay_ms;
|
||||||
|
/* TODO: 替换为你的平台 delay 实现 */
|
||||||
/* TODO: 替换为平台 delay 实现 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 示例:设备描述 */
|
void eeprom_example(void)
|
||||||
static const IntEEPROM24xx_t g_eeprom = {
|
{
|
||||||
.ctx = 0,
|
IntEEPROM24xx_Config_t cfg = {
|
||||||
.dev_addr = (0x50u << 1),
|
.dev_addr = (0x50u << 1),
|
||||||
.page_size = 8u,
|
.page_size = 8u,
|
||||||
.mem_addr_size = 1u,
|
.mem_addr_size = 1u,
|
||||||
.write_cycle_ms = 6u,
|
.write_cycle_ms = 6u,
|
||||||
.timeout_ms = 100u,
|
.timeout_ms = 100u,
|
||||||
.bus_read = your_bus_read,
|
};
|
||||||
.bus_write = your_bus_write,
|
|
||||||
.delay_ms = your_delay_ms,
|
|
||||||
};
|
|
||||||
|
|
||||||
void eeprom_example(void)
|
uint8_t tx[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||||
{
|
|
||||||
uint8_t tx[8] = {1,2,3,4,5,6,7,8};
|
|
||||||
uint8_t rx[8] = {0};
|
uint8_t rx[8] = {0};
|
||||||
|
|
||||||
(void)Int_EEPROM24xx_Write(&g_eeprom, 0x00, tx, sizeof(tx));
|
if (Int_EEPROM24xx_Init(&cfg, your_i2c_read, your_i2c_write, your_delay_ms) != INT_EEPROM_OK)
|
||||||
(void)Int_EEPROM24xx_Read(&g_eeprom, 0x00, rx, sizeof(rx));
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)Int_EEPROM24xx_Write(0x00, tx, sizeof(tx));
|
||||||
|
(void)Int_EEPROM24xx_Read(0x00, rx, sizeof(rx));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,47 @@
|
|||||||
#include "Int_EEPROM24xx.h"
|
#include "Int_EEPROM24xx.h"
|
||||||
|
|
||||||
/* 直接透传到用户提供的总线读回调。 */
|
static IntEEPROM24xx_Config_t g_cfg;
|
||||||
IntEEPROM_Result_t Int_EEPROM24xx_Read(const IntEEPROM24xx_t *dev, uint32_t mem_addr, uint8_t *buf, uint16_t len)
|
static IntEEPROM_I2CRead_t g_read_fn;
|
||||||
|
static IntEEPROM_I2CWrite_t g_write_fn;
|
||||||
|
static IntEEPROM_DelayMs_t g_delay_fn;
|
||||||
|
static uint8_t g_inited;
|
||||||
|
|
||||||
|
IntEEPROM_Result_t Int_EEPROM24xx_Init(const IntEEPROM24xx_Config_t *cfg,
|
||||||
|
IntEEPROM_I2CRead_t read_fn,
|
||||||
|
IntEEPROM_I2CWrite_t write_fn,
|
||||||
|
IntEEPROM_DelayMs_t delay_fn)
|
||||||
{
|
{
|
||||||
if (dev == NULL || buf == NULL || len == 0u || dev->bus_read == NULL)
|
if (cfg == NULL || read_fn == 0 || write_fn == 0)
|
||||||
{
|
{
|
||||||
return INT_EEPROM_ERR_ARG;
|
return INT_EEPROM_ERR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev->bus_read(dev->ctx, dev->dev_addr, mem_addr, dev->mem_addr_size, buf, len, dev->timeout_ms);
|
if (cfg->page_size == 0u || (cfg->mem_addr_size != 1u && cfg->mem_addr_size != 2u))
|
||||||
|
{
|
||||||
|
return INT_EEPROM_ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cfg = *cfg;
|
||||||
|
g_read_fn = read_fn;
|
||||||
|
g_write_fn = write_fn;
|
||||||
|
g_delay_fn = delay_fn;
|
||||||
|
g_inited = 1u;
|
||||||
|
return INT_EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 直接透传到用户提供的总线读回调。 */
|
||||||
|
IntEEPROM_Result_t Int_EEPROM24xx_Read(uint32_t mem_addr, uint8_t *buf, uint16_t len)
|
||||||
|
{
|
||||||
|
if (g_inited == 0u || buf == 0 || len == 0u)
|
||||||
|
{
|
||||||
|
return INT_EEPROM_ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_read_fn(g_cfg.dev_addr, mem_addr, g_cfg.mem_addr_size, buf, len, g_cfg.timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 按页拆分写入,避免跨页写导致 EEPROM 数据回卷或写失败。 */
|
/* 按页拆分写入,避免跨页写导致 EEPROM 数据回卷或写失败。 */
|
||||||
IntEEPROM_Result_t Int_EEPROM24xx_Write(const IntEEPROM24xx_t *dev, uint32_t mem_addr, const uint8_t *buf, uint16_t len)
|
IntEEPROM_Result_t Int_EEPROM24xx_Write(uint32_t mem_addr, const uint8_t *buf, uint16_t len)
|
||||||
{
|
{
|
||||||
uint16_t written = 0;
|
uint16_t written = 0;
|
||||||
uint16_t chunk;
|
uint16_t chunk;
|
||||||
@@ -21,7 +50,7 @@ IntEEPROM_Result_t Int_EEPROM24xx_Write(const IntEEPROM24xx_t *dev, uint32_t mem
|
|||||||
uint16_t room;
|
uint16_t room;
|
||||||
IntEEPROM_Result_t st;
|
IntEEPROM_Result_t st;
|
||||||
|
|
||||||
if (dev == NULL || buf == NULL || len == 0u || dev->page_size == 0u || dev->bus_write == NULL)
|
if (g_inited == 0u || buf == 0 || len == 0u)
|
||||||
{
|
{
|
||||||
return INT_EEPROM_ERR_ARG;
|
return INT_EEPROM_ERR_ARG;
|
||||||
}
|
}
|
||||||
@@ -30,27 +59,26 @@ IntEEPROM_Result_t Int_EEPROM24xx_Write(const IntEEPROM24xx_t *dev, uint32_t mem
|
|||||||
{
|
{
|
||||||
/* 计算当前页内偏移和本次最多可写长度。 */
|
/* 计算当前页内偏移和本次最多可写长度。 */
|
||||||
cur_addr = mem_addr + written;
|
cur_addr = mem_addr + written;
|
||||||
page_off = (uint16_t)(cur_addr % dev->page_size);
|
page_off = (uint16_t)(cur_addr % g_cfg.page_size);
|
||||||
room = (uint16_t)(dev->page_size - page_off);
|
room = (uint16_t)(g_cfg.page_size - page_off);
|
||||||
chunk = (uint16_t)(((len - written) < room) ? (len - written) : room);
|
chunk = (uint16_t)(((len - written) < room) ? (len - written) : room);
|
||||||
|
|
||||||
/* 实际总线写由平台适配层完成。 */
|
/* 实际总线写由平台适配层完成。 */
|
||||||
st = dev->bus_write(dev->ctx,
|
st = g_write_fn(g_cfg.dev_addr,
|
||||||
dev->dev_addr,
|
|
||||||
cur_addr,
|
cur_addr,
|
||||||
dev->mem_addr_size,
|
g_cfg.mem_addr_size,
|
||||||
(const uint8_t *)(buf + written),
|
(const uint8_t *)(buf + written),
|
||||||
chunk,
|
chunk,
|
||||||
dev->timeout_ms);
|
g_cfg.timeout_ms);
|
||||||
if (st != INT_EEPROM_OK)
|
if (st != INT_EEPROM_OK)
|
||||||
{
|
{
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->delay_ms != NULL && dev->write_cycle_ms > 0u)
|
if (g_delay_fn != 0 && g_cfg.write_cycle_ms > 0u)
|
||||||
{
|
{
|
||||||
/* EEPROM 页写后通常需要写周期时间。 */
|
/* EEPROM 页写后通常需要写周期时间。 */
|
||||||
dev->delay_ms(dev->ctx, dev->write_cycle_ms);
|
g_delay_fn(g_cfg.write_cycle_ms);
|
||||||
}
|
}
|
||||||
written = (uint16_t)(written + chunk);
|
written = (uint16_t)(written + chunk);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define INT_EEPROM24XX_H
|
#define INT_EEPROM24XX_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef int32_t IntEEPROM_Result_t;
|
typedef int32_t IntEEPROM_Result_t;
|
||||||
|
|
||||||
@@ -10,51 +9,38 @@ typedef int32_t IntEEPROM_Result_t;
|
|||||||
#define INT_EEPROM_ERR_ARG -1
|
#define INT_EEPROM_ERR_ARG -1
|
||||||
#define INT_EEPROM_ERR_IO -2
|
#define INT_EEPROM_ERR_IO -2
|
||||||
|
|
||||||
/* 底层总线读回调:
|
typedef IntEEPROM_Result_t (*IntEEPROM_I2CRead_t)(uint16_t dev_addr,
|
||||||
* ctx : 用户上下文(可传 I2C 句柄、驱动实例等)
|
|
||||||
* dev_addr : 器件地址(格式由你的平台驱动决定)
|
|
||||||
* mem_addr : EEPROM 内存地址
|
|
||||||
* mem_addr_size : 地址字节数(1 或 2)
|
|
||||||
* timeout_ms : 访问超时(毫秒)
|
|
||||||
*/
|
|
||||||
typedef IntEEPROM_Result_t (*IntEEPROM_BusRead_t)(void *ctx,
|
|
||||||
uint16_t dev_addr,
|
|
||||||
uint32_t mem_addr,
|
uint32_t mem_addr,
|
||||||
uint8_t mem_addr_size,
|
uint8_t mem_addr_size,
|
||||||
uint8_t *buf,
|
uint8_t *buf,
|
||||||
uint16_t len,
|
uint16_t len,
|
||||||
uint32_t timeout_ms);
|
uint32_t timeout_ms);
|
||||||
|
|
||||||
/* 底层总线写回调,参数含义同读回调 */
|
typedef IntEEPROM_Result_t (*IntEEPROM_I2CWrite_t)(uint16_t dev_addr,
|
||||||
typedef IntEEPROM_Result_t (*IntEEPROM_BusWrite_t)(void *ctx,
|
|
||||||
uint16_t dev_addr,
|
|
||||||
uint32_t mem_addr,
|
uint32_t mem_addr,
|
||||||
uint8_t mem_addr_size,
|
uint8_t mem_addr_size,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
uint16_t len,
|
uint16_t len,
|
||||||
uint32_t timeout_ms);
|
uint32_t timeout_ms);
|
||||||
|
|
||||||
typedef void (*IntEEPROM_DelayMs_t)(void *ctx, uint32_t delay_ms);
|
typedef void (*IntEEPROM_DelayMs_t)(uint32_t delay_ms);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void *ctx; /* 用户上下文 */
|
uint16_t dev_addr;
|
||||||
uint16_t dev_addr; /* 器件地址 */
|
uint16_t page_size;
|
||||||
uint16_t page_size; /* 页大小(字节) */
|
uint8_t mem_addr_size; /* 1 or 2 */
|
||||||
uint8_t mem_addr_size; /* 地址字节数:1 或 2 */
|
uint32_t write_cycle_ms;
|
||||||
uint32_t write_cycle_ms; /* 每次页写后等待时间(ms) */
|
uint32_t timeout_ms;
|
||||||
uint32_t timeout_ms; /* 总线访问超时(ms) */
|
} IntEEPROM24xx_Config_t;
|
||||||
IntEEPROM_BusRead_t bus_read;
|
|
||||||
IntEEPROM_BusWrite_t bus_write;
|
|
||||||
IntEEPROM_DelayMs_t delay_ms;
|
|
||||||
} IntEEPROM24xx_t;
|
|
||||||
|
|
||||||
/* 读取 EEPROM。
|
/* 初始化模块:用户传入 I2C 读、写和毫秒延时函数后,即可直接调用读写 API。 */
|
||||||
* 返回 INT_EEPROM_OK 表示成功。
|
IntEEPROM_Result_t Int_EEPROM24xx_Init(const IntEEPROM24xx_Config_t *cfg,
|
||||||
*/
|
IntEEPROM_I2CRead_t read_fn,
|
||||||
IntEEPROM_Result_t Int_EEPROM24xx_Read(const IntEEPROM24xx_t *dev, uint32_t mem_addr, uint8_t *buf, uint16_t len);
|
IntEEPROM_I2CWrite_t write_fn,
|
||||||
|
IntEEPROM_DelayMs_t delay_fn);
|
||||||
|
|
||||||
/* 写入 EEPROM(内部会自动按页拆分写入)。 */
|
IntEEPROM_Result_t Int_EEPROM24xx_Read(uint32_t mem_addr, uint8_t *buf, uint16_t len);
|
||||||
IntEEPROM_Result_t Int_EEPROM24xx_Write(const IntEEPROM24xx_t *dev, uint32_t mem_addr, const uint8_t *buf, uint16_t len);
|
IntEEPROM_Result_t Int_EEPROM24xx_Write(uint32_t mem_addr, const uint8_t *buf, uint16_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user