SPI FLASH扇区擦除方法及步骤详解

目录

一、扇区擦除  Sector Erase  指令 (20h)

         1、步骤

                a、扇区擦除前,必须解锁FLASH,也就是写使能       (06h)

                b、FLASH进行扇区擦除,看第一个图                         (20h)

                c、检查是否擦除 状态寄存器 (05h or 35h)

                d、对FLASH上锁,禁止写入数据        (04h)

        2、编写代码

二、页编程     Page Program   指令(02h)

        1、步骤

        2、编写代码


一、扇区擦除  Sector Erase  指令 (20h)

         1、步骤

                a、扇区擦除前,必须解锁FLASH,也就是写使能       (06h)

 cs拉低之后,直接发送(06h),再将cs拉高,完成写使能。

                b、FLASH进行扇区擦除,看第一个图                         (20h)

cs拉低之后,发送(20h),再发送一个24位地址,cs拉高,完成扇区擦除。

                c、检查是否擦除 状态寄存器 (05h or 35h)

05h表示状态寄存器1,35h表示状态寄存器2 

 这里我们主要用状态寄存器1,因为状态寄存器1包含一个BUSY位,在S0最低位上,如果BUSY位为1,表示还在繁忙中,如果BUSY位为0,表示已经操作完毕(很重要 !!!)下图就是状态寄存器1

                d、对FLASH上锁,禁止写入数据        (04h)

  cs拉低之后,直接发送(04h),再将cs拉高,完成上锁。

        2、编写代码

//写使能
void w25qxx_write_enable(void)
{
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x06
	SPI1_SendByte(0x06);

	//片选引脚拉高	
	W25QXX_SS=1;
}

//读状态寄存器1
uint8_t w25qxx_read_status1(void)
{
	uint8_t status=0;
	
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x05
	SPI1_SendByte(0x05);

	//发送任意参数,读取状态寄存器的值
	status=SPI1_SendByte(0xFF);
	
	//片选引脚拉高	
	W25QXX_SS=1;
	
	return status;
}

//写失能
void w25qxx_write_disable(void)
{
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x04
	SPI1_SendByte(0x04);


	//片选引脚拉高	
	W25QXX_SS=1;
}

//擦除
void w25qxx_erase_sector(uint32_t addr)
{
	uint8_t status=0;

	//执行写使能指令
	w25qxx_write_enable();
	
	//延时一会儿,让片选引脚能够给保持高电平一段时间,让w25qxx识别
	delay_us(1);

	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x20
	SPI1_SendByte(0x20);
	
	//发送24bit的地址
	SPI1_SendByte((addr>>16)&0xFF);
	SPI1_SendByte((addr>>8)&0xFF);
	SPI1_SendByte( addr&0xFF);

	//片选引脚拉高	
	W25QXX_SS=1;
	
	//延时一会儿,让片选引脚能够给保持高电平一段时间,让w25qxx识别
	delay_us(10);
	
	//检查当前是否已经擦除成功
	while(1)
	{
		status=w25qxx_read_status1();
		
		if((status & 0x01) ==0)        //判断最低为是否为0,为0表示操作完毕,退出。
			break;
	
		//每隔1毫秒进行查询
		delay_ms(1);
	
	}
	
	//开启写保护
	w25qxx_write_disable();
}

二、页编程     Page Program   指令(02h)

一次最高只能写入256字节,原因是缓冲区最大接受256个字节

        1、步骤

                a:写使能        (06h)

                b:页写入指令        (02h)

 这里的24位地址是任意地址,不是扇区地址,和(20h)不一样。发送完后cs拉高。

                c:检测是否编程完毕,使用状态寄存器1,和上面红字区域一样。

                d:写失能。

        2、编写代码

uint8_t SPI1_SendByte(uint8_t byte)
{
	/*!< Loop while DR register in not emplty ,等待发送缓冲区为空*/
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

	/*!< Send byte through the SPI1 peripheral ,通过SPI1发送字节*/
	SPI_I2S_SendData(SPI1, byte);

	/*!< Wait to receive a byte ,由于是同步通信,等待接收字节*/
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

	/*!< Return the byte read from the SPI bus ,成功接收从机的字节并返回*/
	return SPI_I2S_ReceiveData(SPI1);
}

//写使能
void w25qxx_write_enable(void)
{
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x06
	SPI1_SendByte(0x06);

	//片选引脚拉高	
	W25QXX_SS=1;
}

//读状态寄存器1
uint8_t w25qxx_read_status1(void)
{
	uint8_t status=0;
	
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x05
	SPI1_SendByte(0x05);

	//发送任意参数,读取状态寄存器的值
	status=SPI1_SendByte(0xFF);
	
	//片选引脚拉高	
	W25QXX_SS=1;
	
	return status;
}

//写失能
void w25qxx_write_disable(void)
{
	//片选引脚拉低
	W25QXX_SS=0;
	
	//发送0x04
	SPI1_SendByte(0x04);


	//片选引脚拉高	
	W25QXX_SS=1;
}

//写数据,一次最高256字节
void w25qxx_write_page(uint32_t addr,uint8_t *pbuf,uint32_t len)
{
	uint8_t status=0;

	//执行写使能指令
	w25qxx_write_enable();
	
	//延时一会儿,让片选引脚能够给保持高电平一段时间,让w25qxx识别
	delay_us(10);

	//片选引脚拉低
	W25QXX_SS=0;
	
	
	//发送0x02
	SPI1_SendByte(0x02);
	
	//发送24bit的地址
	SPI1_SendByte((addr>>16)&0xFF);
	SPI1_SendByte((addr>>8)&0xFF);
	SPI1_SendByte( addr&0xFF);
	
	//发送数据
	while(len--)
		SPI1_SendByte(*pbuf++);

	//片选引脚拉高	
	W25QXX_SS=1;
	
	//延时一会儿,让片选引脚能够给保持高电平一段时间,让w25qxx识别
	delay_us(10);
	
	
	//检查当前是否已经写入成功
	while(1)
	{
		status=w25qxx_read_status1();
		
		if((status & 0x01) ==0)
			break;
	
		//每隔1毫秒进行查询
		delay_ms(1);
	
	}
	
	//开启写保护
	w25qxx_write_disable();
}

验证代码片段

int main(void)
{
    //spi flash初始化
	w25qxx_init();
	
	
	//打印id信息
	printf("w25qxx spi flash id=%04X\r\n",w25qxx_read_id());
	
	//从地址0进行扇区擦除,每次擦除4KB字节
	printf("w25qxx spi flash erase sector at addr 0\r\n");
	w25qxx_erase_sector(0);
	
	
	//从地址0写入64字节数据,写入数据位1~64
	for(i=0; i<64; i++)
		buf[i]=i+1;
	printf("w25qxx spi flash write data at addr 0,data is 1~64\r\n");
	w25qxx_write_page(0,buf,64);
	
	
	//从地址0读取64字节数据
	memset(buf,0,64);
	printf("w25qxx spi flash read data at addr 0:\r\n");
	w25qxx_read_data(0,buf,64);
	
	
	
	for(i=0; i<64; i++)
	{
		printf("%02X ",buf[i]);
	
	}

	printf("\r\n");

    while(1)
    {

    }

}

物联沃分享整理
物联沃-IOTWORD物联网 » SPI FLASH扇区擦除方法及步骤详解

发表评论