139 lines
4.0 KiB
C
139 lines
4.0 KiB
C
/*
|
|
* @Author: mypx
|
|
* @Email: mypx_coder@163.com
|
|
* @Date: 2025-06-19 15:35:35
|
|
* @LastEditors: mypx mypx_coder@163.com
|
|
* @Description:
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include "at24cx.h"
|
|
|
|
// Log tag
|
|
static const char *TAG = "at24c";
|
|
|
|
// Debug macro for logging messages
|
|
#define AT24_DBG(fmt, ...) \
|
|
if (device && device->log) \
|
|
{ \
|
|
device->log(TAG, fmt, ##__VA_ARGS__); \
|
|
}
|
|
|
|
// Define the chip information table
|
|
static const at24cx_chip_info_t chip_info_table[] = {
|
|
{0x0000, 0x007F, 8}, // AT24C01
|
|
{0x0000, 0x00FF, 8}, // AT24C02
|
|
{0x0000, 0x01FF, 9}, // AT24C04
|
|
{0x0000, 0x03FF, 10}, // AT24C08
|
|
{0x0000, 0x3FFF, 16} // AT24C128
|
|
};
|
|
|
|
// Check if the address is within the valid range
|
|
static int check_address_range(at24cx_dev_t *device, uint16_t addr, uint16_t num)
|
|
{
|
|
const at24cx_chip_info_t *info = &chip_info_table[device->chip_model];
|
|
if (addr < info->min_addr || addr + num - 1 > info->max_addr)
|
|
{
|
|
AT24_DBG("Address out of range: min = %04X, max = %04X, requested = %04X - %04X",
|
|
info->min_addr, info->max_addr, addr, addr + num - 1);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Write a single byte to the specified address
|
|
int at24cx_write_byte(at24cx_dev_t *device, uint16_t addr, uint8_t data)
|
|
{
|
|
if (check_address_range(device, addr, 1) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (device != NULL && device->write_bytes)
|
|
{
|
|
return device->write_bytes((uint16_t)device->dev_addr, addr, &data, 1);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Write multiple bytes to the device, supporting cross-page writing
|
|
int at24cx_write(at24cx_dev_t *device, uint16_t start_addr, uint8_t *data_buf, uint16_t write_num)
|
|
{
|
|
if (check_address_range(device, start_addr, write_num) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
uint16_t bytes_written = 0;
|
|
uint16_t current_addr = start_addr;
|
|
uint8_t *current_data = data_buf;
|
|
|
|
// Loop until all data is written
|
|
while (bytes_written < write_num)
|
|
{
|
|
// Calculate the number of bytes that can be written to the current page
|
|
uint16_t bytes_to_write = AT24_MAX_PAGE_SIZE - (current_addr % AT24_MAX_PAGE_SIZE);
|
|
if (bytes_to_write > write_num - bytes_written)
|
|
{
|
|
bytes_to_write = write_num - bytes_written;
|
|
}
|
|
|
|
if (device != NULL && device->write_bytes)
|
|
{
|
|
int ret = device->write_bytes(device->dev_addr, current_addr, current_data, bytes_to_write);
|
|
if (ret != 0)
|
|
{
|
|
AT24_DBG("Failed to write %d bytes at address %04X", bytes_to_write, current_addr);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Update the number of written bytes, current address, and data pointer
|
|
bytes_written += bytes_to_write;
|
|
current_addr += bytes_to_write;
|
|
current_data += bytes_to_write;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Read a single byte from the specified register
|
|
int at24cx_read_byte(at24cx_dev_t *device, uint16_t reg, uint8_t *data)
|
|
{
|
|
if (check_address_range(device, reg, 1) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (device != NULL && device->read_bytes)
|
|
{
|
|
int ret = device->read_bytes(device->dev_addr, reg, data, 1);
|
|
if (ret == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
AT24_DBG("Failed to read byte at register %02X", reg);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Read multiple bytes from the device
|
|
int at24cx_read(at24cx_dev_t *device, uint16_t start_addr, uint8_t *data_buf, uint16_t read_num)
|
|
{
|
|
if (check_address_range(device, start_addr, read_num) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (device != NULL && device->read_bytes)
|
|
{
|
|
int ret = device->read_bytes(device->dev_addr, start_addr, data_buf, read_num);
|
|
if (ret == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
AT24_DBG("Failed to read %d bytes from register %02X", read_num, start_addr);
|
|
}
|
|
return -1;
|
|
}
|