关于W25Q32JVSSIQ的详细内容在之前的两篇文章中已经详细介绍,本文不做太多赘述,如果对芯片的了解有缺失的话,可以参考:
SPI协议——对外部SPI Flash操作-CSDN博客
SPI协议——读取外部SPI Flash ID_spi flash 读取id-CSDN博客
目录
一、代码编写
1.发送/接收单/多个字节的函数
2.实现扇区擦除
3.实现跨页写
4.读取数据
二、运行结果
一、代码编写
1.发送/接收单/多个字节的函数
这样设计代码可以随意选择自己是否忽略发送/接受的数据
void SPI_FLASH_Xfer(uint8_t *snd_buf, uint8_t *recv_buf, int bytes)
{
int i;
uint8_t send_data, recv_data;
for(i = 0; i < bytes; i ++)
{
send_data = (snd_buf != NULL) ? snd_buf[i] : 0xFF;
recv_data = SPI_FLASH_SendByte(send_data);
if( recv_buf != NULL )
{
recv_buf[i] = recv_data;
}
printf("Sending: 0x%02X, Received: 0x%02X\n", send_data, recv_data);
}
HAL_Delay(1);
}
2.实现扇区擦除
int New_SPI_FLASH_SectorErase(uint32_t addr, uint32_t size)
{
uint32_t sector, first, last;
uint32_t address;
int rv;
first = addr / Sector_Size;
last = (addr + size - 1) / Sector_Size;
/* Start to erase all sectors */
for (sector = first; sector <= last; sector++)
{
address = sector * Sector_Size;
printf("Norflash Erase Sector@%lx ...\r\n", address);
SPI1_FLASH_WaitEnd();
SPI1_FLASH_WriteEnable();
cs_low();
SPI_FLASH_SendByte(0x20); // 发送扇区擦除命令
/* Send the addr */
SPI_FLASH_SendByte((address & 0xFF0000) >> 16);
SPI_FLASH_SendByte((address & 0xFF00) >> 8);
SPI_FLASH_SendByte(address & 0xFF);
cs_high();
// 确保擦除完成
SPI1_FLASH_WaitEnd();
HAL_Delay(10); // 增加延时,确保擦除完成
}
// 检查整个擦除区域是否已擦除
rv = SPI_FLASH_VerifyErase(addr, size);
if (rv != 0)
{
printf("Erase the sector error\n");
return -1;
}
else
{
printf("Erase ok\n");
}
return 0;
}
3.实现跨页写
int New_SPI_FLASH_PageWrite( uint32_t addr, uint8_t *data, uint32_t size)
{
uint32_t first, last, page;
uint32_t address, ofset, len;
uint8_t buf[Page_Size+5];
int bytes = 0;
if( addr + size > 0x400000 )
return -1;
/* find the fist and the last page */
first = addr / Page_Size;
last = ( addr + size - 1 ) / Page_Size;
printf("Norflash Write %ld Bytes to addr@0x%lx Begin...\r\n", size, addr );
/*Initial address in page and offset in buffer */
address = addr;
ofset = 0;
/* Start to write to all pages */
for( page = first; page <= last; page ++)
{
len = Page_Size - ( address % Page_Size );
len = len > size ? size : len;
bytes = 0;
printf("Norflash write addr@0x%lx, %lu bytes,and the data is %s \r\n", addr, len, data);
buf[bytes++] = 0x02;
buf[bytes++] = (addr & 0xFF0000) >> 16 ;
buf[bytes++] = (addr & 0xFF00) >> 8 ;
buf[bytes++] = (addr & 0xFF);
/* send command and data */
memcpy(&buf[bytes], data+ofset, len);
bytes += len;
printf("Norflash write addr@0x%lx, %lu bytes, data : ", address, len);
for( int i = 4; i < bytes; i++ )
{
printf("0x%02x", buf[i]);
printf("\n");
}
SPI1_FLASH_WriteEnable();
cs_low();
SPI_FLASH_Xfer(buf, NULL, bytes);
cs_high();
SPI1_FLASH_WaitEnd();
addr += len;
ofset += len;
size -= len;
}
HAL_Delay(10);
printf("Norflash WriteByte@0x%lx done.\r\n", addr);
return 0;
}
4.读取数据
void New_SPI_FLASH_BufferRead(uint32_t addr, uint8_t *buffer, uint32_t size)
{
uint8_t cmd[4];
cmd[0] = 0x03; // Read Data command
cmd[1] = (addr >> 16) & 0xFF;
cmd[2] = (addr >> 8) & 0xFF;
cmd[3] = addr & 0xFF;
cs_low();
//发送读取命令和地址
SPI_FLASH_Xfer(cmd, NULL, 4);
//读取数据
SPI_FLASH_Xfer(NULL, buffer, size);
cs_high();
// 调试输出,可选项,用于验证发送的命令和接收到的数据
/* printf("SPI Flash Read: Address = 0x%lx, Data: ", addr);
for (int i = 0; i < size; i++)
{
printf("0x%02x ", buffer[i]);
}
printf("\n");
*/
}
二、运行结果