STM32系列 STM32F4xx SPI Flash-读写操作

W25Q32JV是华邦推出的一款spi flash,32J表示32M-bit,相当于4M
关于型号命名如下
STM32系列 STM32F4xx SPI Flash-读写操作_第1张图片
对于W25Q32JV:
page为最大编程单位,1page = 256bytes
sector为最小擦除单位,1sector = 16pages = 4KB = 4096bytes
还支持半块擦除(32KB block erase)、块擦除(64KB block erase)和整片擦除(chip erase)

PIN描述

  • Chip Select(/CS):芯片使能和禁用引脚,当/CS为高时,禁用设备,串行数据输出(DO, IO0, IO1, IO2, IO3)引脚处于高阻抗状态,除非进行内部擦除,程序或写状态寄存器循环,否则设备处于待机状态,当/CS为低时,将使能设备,可以向设备写入指令并从设备读取数据。
  • Serial Data Input, Output and IOs(DI, DO and IO0, IO1, IO2,IO3):串行数据输入,输出和IOs,支持standard SPI,DualSPI和QuadSPI操作,标准SPI,使用DI引脚写入指令、地址或数据,使用DO引脚读取数据或状态。当QE =1时,/WP引脚变为IO2,/HOLD引脚变为IO3。
  • Write Protect(/WP):写保护引脚,用于防止状态寄存器被写入。与状态寄存器的块保护位和状态寄存器保护位一起使用。
  • HOLD(/HOLD):当设备处于活动状态时,/HOLD引脚允许设备暂停。当/HOLE为低,/CS为低时,DO引脚出去高阻抗,此时,DI和CLK引脚上的信号将被忽略。当多个设备共享形同的SPI时,/HOLD引脚非常有用。
  • Serial Clock(CLK):为串行输入和输出操作提供同步时钟。

状态和配置寄存器

W25Q32JV提供了三个状态和配置寄存器。
STM32系列 STM32F4xx SPI Flash-读写操作_第2张图片

  • Erase/Write in Progress(BUSY) - 只读,当设备执行页编程,四页编程,扇区擦除,块擦除,整擦除,写状态寄存器或删除/程序安全寄存器指令时,此位置为1,在此期间,除读取状态寄存器和擦除暂停指令外,将忽略其他指令。当操作完成后,busy位将被清为0,表示设备准备好接受下一步指令。
  • Write Enable Latch(WEL) - 只读,状态寄存器(S1)中的一个只读位,在执行写使能指令后,被置为1,当写入被禁用时,WEL位被清为0。“写禁用”,“页编程”,“四页编程”,“扇区擦除”,“块擦除”,“整片擦除”,“写状态寄存器”,“擦除安全寄存器”和“程序安全寄存器”这些指令完成后,自动回到写禁用状态。
  • Block Protect Bits(BP2, BP1, BP0) - 块保护位,是状态寄存器中提供写保护控制和状态的非易失读/写位,可以通过写状态寄存器指令来设置。
  • Status Register Protect(SRP, SRL),这两个位 与 WP 引脚一起, 用于控制对状态寄存器的写

写操作

  1. 发送写使能指令(06h),
  2. 发送页编程指令(02h),如果要对整个256字节的页面进行编程,最后一个地址字节应该设置为0,可以对少于256字节进行编程,而不会对同一页的其他字节产生影响。如果发送到设备的字节数超过256,则将自动切换行道页面的开头并覆盖之间的数据。
void FLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
	/*Set /CS bit low*/
	GPIO_ResetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);

	/*Send write enable*/
	FLASH_SendByte(0x06);

	/*Set /CS bit high */
	GPIO_SetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);

	/*Select the FLASH: Chip Select low */
	GPIO_ResetBits(FLASH_CS_GPIO_PORT, sFLASH_CS_PIN)
	/*Send page program*/
	FLASH_SendByte(0x02);
	/*Send WriteAddr high nibble address byte to write to */
	FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
	/*Send WriteAddr medium nibble address byte to write to */
	FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
	/*Send WriteAddr low nibble address byte to write to */
	FLASH_SendByte(WriteAddr & 0xFF);

	/*while there is data to be written on the FLASH */
	while (NumByteToWrite--)
	{
		/*Send the current byte */
		FLASH_SendByte(*pBuffer);
		/*Point on the next byte to be written */
		pBuffer++;
	}

	/*Deselect the FLASH: Chip Select high */
	GPIO_SetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);

	/*Wait the end of Flash writing */
	FLASH_WaitForWriteEnd();
}

读操作

  1. 发送读数据指令(03h)。
void FLASH_ReadPage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
	/*Set /CS bit low*/
	GPIO_ResetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN)

	/*!Send read data */
	FLASH_SendByte(0x03);

	/*Send ReadAddr high nibble address byte to read from */
	FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
	/*Send ReadAddr medium nibble address byte to read from */
	FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
	/*Send ReadAddr low nibble address byte to read from */
	FLASH_SendByte(ReadAddr & 0xFF);

	/*! Read data */
	while (NumByteToRead--) 
	{
		/*Read a byte from the FLASH */
		*pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
		/*Point to the next location where the byte read will be saved */
		pBuffer++;
	}

	/*Set /CS bit high */
	GPIO_SetBits(sFLASH_CS_GPIO_PORT, sFLASH_CS_PIN) 
}

擦除操作

  1. 发送写使能指令(06h),
  2. 发送扇区擦除指令(20h)。
void FLASH_EraseSector(uint32_t SectorAddr)
{
	/*Set /CS bit low*/
	GPIO_ResetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);
	/*Send write enable*/
	FLASH_SendByte(0x06);
	/*Set /CS bit high */
	GPIO_SetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);

	/*Select the FLASH: Chip Select low */
	GPIO_ResetBits(FLASH_CS_GPIO_PORT, sFLASH_CS_PIN)
	/*Send Sector Erase instruction */
	FLASH_SendByte(0x20);
	/*Send SectorAddr high nibble address byte */
	FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
	/*Send SectorAddr medium nibble address byte */
	FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
	/*Send SectorAddr low nibble address byte */
	FLASH_SendByte(SectorAddr & 0xFF);
	/*Deselect the FLASH: Chip Select high */
	GPIO_SetBits(FLASH_CS_GPIO_PORT, FLASH_CS_PIN);

	/*Wait the end of Flash writing */
	FLASH_WaitForWriteEnd();
}

注:
Flash在写数据之前,先进行Erase操作,其实Erase操作就是往Flash中写FF,最小Erase单位为Sector,也支持32KB Block Erase(52h),64KB Block Erase(D8h)和Chip Erase(C7h/60h)。

如有不足,还望大家指正,互相学习,谢谢!

你可能感兴趣的:(STM32系列 STM32F4xx SPI Flash-读写操作)