#include "bsp_w25q.h" #include "spi.h" #include #include "app_leakage.h" /* spi flash 片选引脚 - pb12 */ #define W25Q32_CS_LOW() HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_RESET) #define W25Q32_CS_HIGH() HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_SET) /* spi 传输函数 */ static void w25q32_spi_transmit(uint8_t *data, uint16_t size) { HAL_SPI_Transmit(&hspi2, data, size, HAL_MAX_DELAY); } static void w25q32_spi_receive(uint8_t *data, uint16_t size) { HAL_SPI_Receive(&hspi2, data, size, HAL_MAX_DELAY); } static uint8_t w25q32_spi_transmit_receive(uint8_t data) { uint8_t rx_data; HAL_SPI_TransmitReceive(&hspi2, &data, &rx_data, 1, HAL_MAX_DELAY); return rx_data; } /* 内部函数声明 */ static void w25q32_init(void); static void w25q32_read(uint32_t addr, uint8_t *data, uint32_t len); static void w25q32_write(uint32_t addr, uint8_t *data, uint32_t len); static void w25q32_chip_erase(void); static void w25q32_write_enable(void); static void w25q32_write_disable(void); static uint8_t w25q32_read_status_reg(void); static void w25q32_wait_for_write_end(void); static void w25q32_block_erase(uint32_t block_addr); static void w25q32_page_write(uint32_t addr, uint8_t *data, uint16_t len); static uint8_t w25q32_read_id(void); static void w25q32_power_down(void); static void w25q32_wake_up(void); /* w25q32 对象实例 */ w25q32_t w25q32 = { .init = w25q32_init, .read = w25q32_read, .write = w25q32_write, .chip_erase = w25q32_chip_erase, .sector_erase = w25q32_sector_erase, }; /* 从W25Q32读取设备信息到app_leakage */ static void gui_tjc_hmi_read_device_info_from_w25q(void) { /* 创建一个临时缓冲区 */ app_leakage_sub_device_flash_data_t temp_buffer[APP_LEAKAGE_SUB_DEVICE_NUM]; /* 一次性读取所有设备信息 */ w25q32.read(W25Q32_DEVICE_INFO_ADDR, (uint8_t*)temp_buffer, DEVICE_INFO_STORAGE_SIZE); /* 检查数据有效性 */ uint8_t data_valid = 1; for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { /* 如果所有字段都是0xFF,说明是空数据 */ if(temp_buffer[i].state == 0xFF && temp_buffer[i].com == 0xFF && temp_buffer[i].modbus_id == 0xFF) { data_valid = 0; break; } } if(data_valid) { /* 复制到app_leakage结构体中 */ for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { leakage.sub_device_data[i].flash_data = temp_buffer[i]; } } else { /* Flash为空,初始化设备信息为默认值 */ for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { memset(&leakage.sub_device_data[i].flash_data, 0, sizeof(app_leakage_sub_device_flash_data_t)); leakage.sub_device_data[i].flash_data.state = DISABLE; } } } /* 初始化函数 */ static void w25q32_init(void) { W25Q32_CS_HIGH(); /* 初始时片选拉高 */ w25q32_wake_up(); /* 唤醒芯片 */ gui_tjc_hmi_read_device_info_from_w25q(); } /* 读取芯片id */ static uint8_t w25q32_read_id(void) { uint8_t id = 0; uint8_t cmd = W25Q32_JEDEC_ID; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); w25q32_spi_receive(&id, 1); /* 忽略前两个字节 */ w25q32_spi_receive(&id, 1); w25q32_spi_receive(&id, 1); /* 设备id在第三个字节 */ W25Q32_CS_HIGH(); return id; } /* 写使能 */ static void w25q32_write_enable(void) { uint8_t cmd = W25Q32_WRITE_ENABLE; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); W25Q32_CS_HIGH(); } /* 写禁止 */ static void w25q32_write_disable(void) { uint8_t cmd = W25Q32_WRITE_DISABLE; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); W25Q32_CS_HIGH(); } /* 读取状态寄存器 */ static uint8_t w25q32_read_status_reg(void) { uint8_t status; uint8_t cmd = W25Q32_READ_STATUS_REG1; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); status = w25q32_spi_transmit_receive(0x00); W25Q32_CS_HIGH(); return status; } /* 等待写入完成 */ static void w25q32_wait_for_write_end(void) { while (w25q32_read_status_reg() & W25Q32_STATUS_BUSY) { /* 可添加延时或看门狗喂狗 */ } } /* 扇区擦除 (4kb) */ void w25q32_sector_erase(uint32_t sector_addr) { uint8_t cmd[4]; /* 确保地址是4k对齐 */ sector_addr &= ~(W25Q32_SECTOR_SIZE - 1); w25q32_write_enable(); cmd[0] = W25Q32_SECTOR_ERASE; cmd[1] = (sector_addr >> 16) & 0xFF; cmd[2] = (sector_addr >> 8) & 0xFF; cmd[3] = sector_addr & 0xFF; W25Q32_CS_LOW(); w25q32_spi_transmit(cmd, 4); W25Q32_CS_HIGH(); w25q32_wait_for_write_end(); } /* 块擦除 (64kb) */ static void w25q32_block_erase(uint32_t block_addr) { uint8_t cmd[4]; /* 确保地址是64k对齐 */ block_addr &= ~(W25Q32_BLOCK_SIZE - 1); w25q32_write_enable(); cmd[0] = W25Q32_BLOCK_ERASE_64K; cmd[1] = (block_addr >> 16) & 0xFF; cmd[2] = (block_addr >> 8) & 0xFF; cmd[3] = block_addr & 0xFF; W25Q32_CS_LOW(); w25q32_spi_transmit(cmd, 4); W25Q32_CS_HIGH(); w25q32_wait_for_write_end(); } /* 整片擦除 */ static void w25q32_chip_erase(void) { uint8_t cmd = W25Q32_CHIP_ERASE; w25q32_write_enable(); W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); W25Q32_CS_HIGH(); w25q32_wait_for_write_end(); } /* 页写入 (最大256字节) */ static void w25q32_page_write(uint32_t addr, uint8_t *data, uint16_t len) { uint8_t cmd[4]; if (len > W25Q32_PAGE_SIZE) { len = W25Q32_PAGE_SIZE; } w25q32_write_enable(); cmd[0] = W25Q32_PAGE_PROGRAM; cmd[1] = (addr >> 16) & 0xFF; cmd[2] = (addr >> 8) & 0xFF; cmd[3] = addr & 0xFF; W25Q32_CS_LOW(); w25q32_spi_transmit(cmd, 4); w25q32_spi_transmit(data, len); W25Q32_CS_HIGH(); w25q32_wait_for_write_end(); } /* 任意长度写入 */ static void w25q32_write(uint32_t addr, uint8_t *data, uint32_t len) { uint32_t page_remaining; uint32_t offset = 0; while (len > 0) { /* 计算当前页剩余字节数 */ page_remaining = W25Q32_PAGE_SIZE - (addr % W25Q32_PAGE_SIZE); /* 本次写入的长度 */ uint32_t write_len = (len < page_remaining) ? len : page_remaining; /* 写入一页数据 */ w25q32_page_write(addr, &data[offset], write_len); /* 更新地址和偏移 */ addr += write_len; offset += write_len; len -= write_len; } } /* 读取数据 */ static void w25q32_read(uint32_t addr, uint8_t *data, uint32_t len) { uint8_t cmd[4]; cmd[0] = W25Q32_READ_DATA; cmd[1] = (addr >> 16) & 0xFF; cmd[2] = (addr >> 8) & 0xFF; cmd[3] = addr & 0xFF; W25Q32_CS_LOW(); w25q32_spi_transmit(cmd, 4); w25q32_spi_receive(data, len); W25Q32_CS_HIGH(); } /* 进入掉电模式 */ static void w25q32_power_down(void) { uint8_t cmd = W25Q32_POWER_DOWN; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); W25Q32_CS_HIGH(); } /* 唤醒芯片 */ static void w25q32_wake_up(void) { uint8_t cmd = W25Q32_RELEASE_POWER_DOWN; W25Q32_CS_LOW(); w25q32_spi_transmit(&cmd, 1); W25Q32_CS_HIGH(); HAL_Delay(5); /* 等待芯片唤醒 */ }