STM32读写EEPROM
代码如下
#include "i2c.h" #include <string.h> /* M24C64设备地址(A0/A1/A2接地,7位地址为0x50,左移1位后为0xA0) */ #define EEPROM_ADDR (0x50 << 1) #define M24C64_PAGE_SIZE 32 // 页面大小:32字节 #define M24C64_WRITE_DELAY_MS 5 // 写入周期:5毫秒 #define EEPROM_PARAM_ADDR 0x0000 // EEPROM参数存储起始地址 // 参数结构体定义 typedef struct { uint8_t data[256]; // 数据缓冲区:256字节 } Param_t; /** * @brief 向M24C64 EEPROM写入Param_t结构体数据 * @param hi2c: I2C句柄指针 * @param param: 指向要写入的Param_t结构体的指针 * @retval HAL_StatusTypeDef: HAL_OK表示成功,HAL_ERROR表示失败 */ HAL_StatusTypeDef EEPROM_WriteParam(I2C_HandleTypeDef *hi2c, Param_t *param) { uint8_t *data = (uint8_t *)param; // 将结构体转换为字节数组 uint16_t size = sizeof(Param_t); // Param_t结构体大小(256字节) uint16_t addr = EEPROM_PARAM_ADDR; // 当前内存地址 uint16_t bytes_written = 0; // 已写入字节计数 while (bytes_written < size) { // 计算当前页面剩余字节数 uint16_t page_remain = M24C64_PAGE_SIZE - (addr % M24C64_PAGE_SIZE); // 确定本次写入的块大小(取剩余数据或页面剩余空间的最小值) uint16_t chunk_size = (size - bytes_written) > page_remain ? page_remain : (size - bytes_written); // 准备16位地址字节(高字节在前) uint8_t addr_bytes[2] = { (uint8_t)(addr >> 8), (uint8_t)(addr & 0xFF) }; // 合并地址和数据到缓冲区 uint8_t buffer[M24C64_PAGE_SIZE + 2]; buffer[0] = addr_bytes[0]; buffer[1] = addr_bytes[1]; memcpy(&buffer[2], &data[bytes_written], chunk_size); // 向EEPROM写入数据 if (HAL_I2C_Master_Transmit(hi2c, EEPROM_ADDR, buffer, chunk_size + 2, HAL_MAX_DELAY) != HAL_OK) { return HAL_ERROR; } // 等待EEPROM写入周期完成 HAL_Delay(M24C64_WRITE_DELAY_MS); // 更新地址和已写入字节数 bytes_written += chunk_size; addr += chunk_size; } return HAL_OK; } /** * @brief 从M24C64 EEPROM读取Param_t结构体数据 * @param hi2c: I2C句柄指针 * @param param: 指向存储读取数据的Param_t结构体的指针 * @retval HAL_StatusTypeDef: HAL_OK表示成功,HAL_ERROR表示失败 */ HAL_StatusTypeDef EEPROM_ReadParam(I2C_HandleTypeDef *hi2c, Param_t *param) { uint8_t data[sizeof(Param_t)]; // 存储原始数据的缓冲区 uint16_t mem_addr = EEPROM_PARAM_ADDR; // 读取起始地址 // 从EEPROM读取数据 if (HAL_I2C_Mem_Read(hi2c, EEPROM_ADDR, mem_addr, I2C_MEMADD_SIZE_16BIT, data, sizeof(Param_t), HAL_MAX_DELAY) != HAL_OK) { return HAL_ERROR; } // 将原始数据复制到Param_t结构体 memcpy(param, data, sizeof(Param_t)); return HAL_OK; } /** * @brief 测试EEPROM的写入和读取功能 * @param 无 * @retval 无 */ void EEPROM_Test(void) { Param_t write_param; // 用于写入测试的结构体 Param_t read_param; // 用于读取测试的结构体 // 用测试数据填充write_param(0到255的循环模式) for (uint16_t i = 0; i < sizeof(Param_t); i++) { write_param.data[i] = (uint8_t)(i % 256); } // 向EEPROM写入数据 printf("正在写入数据到EEPROM...\n"); if (EEPROM_WriteParam(&hi2c2, &write_param) == HAL_OK) { printf("写入成功!\n"); } else { printf("写入失败!\n"); } // 从EEPROM读取数据 printf("正在从EEPROM读取数据...\n"); if (EEPROM_ReadParam(&hi2c2, &read_param) == HAL_OK) { printf("读取成功!\n"); } else { printf("读取失败!\n"); } }