#include "bsp_w25q.h" #include "spi.h" #include "main.h" /* spi flash 片选引脚 - pb12 */ #define W25Q32_CS_LOW() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET) #define W25Q32_CS_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 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_sector_erase(uint32_t sector_addr); 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, }; /* 初始化函数 */ static void w25q32_init(void) { W25Q32_CS_HIGH(); /* 初始时片选拉高 */ w25q32_wake_up(); /* 唤醒芯片 */ } /* 读取芯片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) */ static 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); /* 等待芯片唤醒 */ }