/** * @file eeprom_fm24.c * @author xxx * @date 2023-08-29 07:58:27 * @brief 用于实现FM24 EEPROM相关的读写操作 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include "eeprom_fm24.h" #include "delay.h" //========在此设定芯片地址============= #define W_ADD_COM 0xa0 // 写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0 #define R_ADD_COM 0xa1 // 读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1 //=======在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512 //=======在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512 #define FM24_SPI SPI1 #define EEPROM_FM24_CS_PORT EE3_CS_GPIO_Port #define EEPROM_FM24_CS_PIN EE3_CS_Pin #define EEPROM_FM24_MOSI_PORT SPI_MOSI_GPIO_Port #define EEPROM_FM24_MOSI_PIN SPI_MOSI_Pin #define EEPROM_FM24_MISO_PORT SPI_MISO_GPIO_Port #define EEPROM_FM24_MISO_PIN SPI_MISO_Pin #define EEPROM_FM24_SCK_PORT SPI_CLK_GPIO_Port #define EEPROM_FM24_SCK_PIN SPI_CLK_Pin static fm24_t _eeprom_fm24; void eeprom_fm24_init(void) { spi_gpio_group_t gpios; spi_normal_config_t cfg; osel_memset((uint8_t *)&cfg, 0, sizeof(spi_normal_config_t)); // 创建CS引脚 gpios.cs = gpio_create(EEPROM_FM24_CS_PORT, EEPROM_FM24_CS_PIN); gpios.mosi = gpio_create(EEPROM_FM24_MOSI_PORT, EEPROM_FM24_MOSI_PIN); gpios.sck = gpio_create(EEPROM_FM24_SCK_PORT, EEPROM_FM24_SCK_PIN); gpios.miso = gpio_create(EEPROM_FM24_MISO_PORT, EEPROM_FM24_MISO_PIN); gpios.rst = gpio_create(NULL, 0); gpios.rdy = gpio_create(NULL, 0); // 创建SPI对象 eeprom_fm24_get()->spi = spi_create(SPI_TYPE_NORMAL, gpios, 0); DBG_ASSERT(eeprom_fm24_get() != NULL __DBG_LINE); cfg.cmd_rdsr = FM24_CMD_RDSR; cfg.cmd_wrsr = FM24_CMD_WRSR; cfg.cmd_wren = FM24_CMD_WREN; cfg.cmd_wrdi = FM24_CMD_WRDI; cfg.cmd_write = FM24_CMD_WRITE; cfg.cmd_read = FM24_CMD_READ; cfg.dummy_byte = FM24_DUMMY_BYTE; cfg.address_bytes = 2; cfg.page_size = FM24_PAGE_SIZE; cfg.total_size = FM24_SIZE; cfg.continuous_write = FALSE; osel_memcpy((uint8_t *)&eeprom_fm24_get()->spi->cfg, (uint8_t *)&cfg, sizeof(spi_normal_config_t)); // 使能SPI eeprom_fm24_get()->spi->interface.hardware_enable(eeprom_fm24_get()->spi, FM24_SPI); // 这里需要复位下SPI,否则读出的数据不对 eeprom_fm24_get()->spi->interface.u.normal.spi_reset(eeprom_fm24_get()->spi); eeprom_fm24_write_protection_close(); // eeprom_fm24_test(); } fm24_t *eeprom_fm24_get(void) { return &_eeprom_fm24; } void eeprom_fm24_dinit(void) { LL_SPI_Disable(FM24_SPI); GPIO_SET_ANALOG(eeprom_fm24_get()->spi->gpios.mosi->port, eeprom_fm24_get()->spi->gpios.mosi->pin); GPIO_SET_ANALOG(eeprom_fm24_get()->spi->gpios.miso->port, eeprom_fm24_get()->spi->gpios.miso->pin); GPIO_SET_ANALOG(eeprom_fm24_get()->spi->gpios.sck->port, eeprom_fm24_get()->spi->gpios.sck->pin); GPIO_SET_ANALOG(eeprom_fm24_get()->spi->gpios.cs->port, eeprom_fm24_get()->spi->gpios.cs->pin); } void eeprom_fm24_enable(void) { uint16_t count = 100; LL_SPI_Enable(FM24_SPI); // 判断SPI是否使能成功 while (LL_SPI_IsEnabled(FM24_SPI) != 1) { if (count-- == 0) { return; } else { __NOP(); } } } void eeprom_fm24_disable(void) { uint16_t count = 100; LL_SPI_Disable(FM24_SPI); // 判断SPI是否关闭成功 while (LL_SPI_IsEnabled(FM24_SPI) != 0) { if (count-- == 0) { return; } else { __NOP(); } } } /** * @brief 关闭EEPROM FM24的写保护 * * 此函数用于关闭EEPROM FM24的写保护功能,允许对其进行写操作。 * * 调用此函数前,应确保EEPROM FM24的SPI接口已正确初始化。 */ void eeprom_fm24_write_protection_close(void) { DBG_ASSERT(eeprom_fm24_get()->spi != NULL __DBG_LINE); eeprom_fm24_enable(); eeprom_fm24_get()->spi->interface.u.normal.spi_write_reg(eeprom_fm24_get()->spi, eeprom_fm24_get()->spi->cfg.cmd_wrsr, 0); eeprom_fm24_disable(); } /** * @brief 获取EEPROM FM24的写保护状态 * * 获取EEPROM FM24的写保护状态。 * * @return BOOL 返回TRUE表示没有写保护,返回FALSE表示有写保护 */ BOOL eeprom_fm24_write_protection_state(void) { DBG_ASSERT(eeprom_fm24_get()->spi != NULL __DBG_LINE); eeprom_fm24_enable(); eeprom_fm24_get()->write_protection.data = eeprom_fm24_get()->spi->interface.u.normal.spi_read_reg(eeprom_fm24_get()->spi, eeprom_fm24_get()->spi->cfg.cmd_rdsr); eeprom_fm24_disable(); if (eeprom_fm24_get()->write_protection.bits.bp0 == 1 || eeprom_fm24_get()->write_protection.bits.bp1 == 1 || eeprom_fm24_get()->write_protection.bits.wpen == 1) { return FALSE; } else { return TRUE; } } BOOL eeprom_fm24_write(uint32_t write_addr, uint8_t *data, uint16_t length) { BOOL ret = FALSE; if (length == 0) { return ret; } // 开启和关闭SPI对读写实时性有影响 eeprom_fm24_enable(); ret = eeprom_fm24_get()->spi->interface.u.normal.spi_write(eeprom_fm24_get()->spi, write_addr, data, length); eeprom_fm24_disable(); return ret; } BOOL eeprom_fm24_read(uint32_t read_addr, uint8_t *data, uint16_t length) { BOOL ret = FALSE; if (length == 0) { return ret; } // 开启和关闭SPI对读写实时性有影响 eeprom_fm24_enable(); ret = eeprom_fm24_get()->spi->interface.u.normal.spi_read(eeprom_fm24_get()->spi, read_addr, data, length); eeprom_fm24_disable(); return ret; } BOOL eeprom_fm24_test(void) { const uint8_t buf_size = 5; uint16_t test_address = FM24_TEST_PAGE * FM24_PAGE_SIZE; uint8_t buf[buf_size]; uint8_t rbuf[buf_size]; osel_memset(buf, 0, buf_size); osel_memset(rbuf, 0, buf_size); buf[0] = 0xD5; buf[1] = 0xC8; buf[2] = 0x00; buf[3] = 0x01; buf[4] = 0x02; buf[buf_size - 1] = 0xfe; eeprom_fm24_write(test_address, buf, buf_size); __NOP(); eeprom_fm24_read(test_address, rbuf, buf_size); if (osel_memcmp(buf, rbuf, buf_size) == 0) { return TRUE; } else { return FALSE; } } /** * @brief 获取FM24 EEPROM的状态 * * 获取FM24 EEPROM的当前状态。该函数始终返回TRUE,表示EEPROM正常工作。 * * @return BOOL 始终返回TRUE */ BOOL eeprom_fm24_status_get(void) { return TRUE; }