polarimeter_software/User/driver/at24cx/at24cx.c
2025-09-30 10:37:23 +08:00

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;
}