精华内容
下载资源
问答
  • stm32 W25QXX系列驱动 W25Q80 W25Q16 W25Q32 W25Q64 W25Q128 W25Q256
    2021-05-03 11:38:45

    头文件

    #ifndef W25QXX__H
    #define W25QXX__H
    #include "sys.h"
    
    
    #define W25Q80 	0XEF13 	
    #define W25Q16 	0XEF14
    #define W25Q32 	0XEF15
    #define W25Q64 	0XEF16
    #define W25Q128	0XEF17
    #define W25Q256 0XEF18
    
    #define W25QXX_CS	PAout(4)
    
    //指令表
    #define W25X_WriteEnable				0x06 
    #define W25X_WriteDisable				0x04 
    #define W25X_ReadStatusReg			0x05 
    #define W25X_WriteStatusReg			0x01 
    #define W25X_ReadData						0x03 
    #define W25X_FastReadData				0x0B 
    #define W25X_FastReadDual				0x3B 
    #define W25X_PageProgram				0x02 
    #define W25X_BlockErase					0xD8 
    #define W25X_SectorErase				0x20 
    #define W25X_ChipErase					0xC7 
    #define W25X_PowerDown					0xB9 
    #define W25X_ReleasePowerDown		0xAB 
    #define W25X_DeviceID						0xAB 
    #define W25X_ManufactDeviceID		0x90 
    #define W25X_JedecDeviceID			0x09
    #define W25X_Enable_Rest 				0x66
    #define W25X_Rest_Device				0x99
    #define W25X_Enter_4_Addres			0xb7
    #define W25X_Read_4_Addres      0x13
    #define W25X_Write_4_Addres     0x02
    #define W25X_Exit_4_Addres  	0xe9
    void W25QXX_Init(void);
    u16  W25QXX_ReadID(void);  	    		//读取FLASH ID
    u8	 W25QXX_Read_SR(void);        		//读取状态寄存器 
    void W25QXX_Write_SR(u8 sr);  			//写状态寄存器
    void W25QXX_Write_Enable(void);  		//写使能 
    void W25QXX_Write_Disable(void);		//写保护
    void W25QXX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u32 NumByteToWrite);
    void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u32 NumByteToRead);   //读取flash
    void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u32 NumByteToWrite);//写入flash
    void W25QXX_Erase_Chip(void);    	  	//整片擦除
    void W25QXX_Erase_Sector(u32 Dst_Addr);	//扇区擦除
    void W25QXX_Wait_Busy(void);           	//等待空闲
    void W25QXX_PowerDown(void);        	//进入掉电模式
    void W25QXX_WAKEUP(void);				//唤醒
    void W25XX_Reset_With_Soft(void);//软件复位W25qXX
    #endif 
    

    访问W25Q256的所有地址(32MB)需要使用4字节地址,使用3字节地址只能访问16MB的空间,根据需要开启

    .c文件

    #include "spi.h"
    #include "w25qxx.h"
    u16 W25QXX_TYPE=W25Q256;	//默认是W25Q32
    
    
    #define ENABLE_W25Q258 1//要使用W25Q256的32MB空间时,设置1,否则为0
    
    
    //软件复位W25qXX
    void W25XX_Reset_With_Soft(void){
      W25QXX_CS=0;                             //使能器件
      SPI1_ReadWriteByte(W25X_Enable_Rest);   //发送允许复位命令
      W25QXX_CS=1;                            //取消片选   
      W25QXX_CS=0;                             //使能器件
      SPI1_ReadWriteByte(W25X_Rest_Device);   //发送允许复位命令
      W25QXX_CS=1;                             //取消片选   
    }
    
    	#if  ENABLE_W25Q258                   
    	
    //进入4字节地址模式	
    void W25QXX_Enter_4Byte(){
    	W25QXX_CS=0;
    	SPI1_ReadWriteByte(W25X_Enter_4_Addres);  
    	W25QXX_CS=1;
    }
    
    //退出4字节地址模式
    void W25QXX_Exit_4Byte(){
    	W25QXX_CS=0;
    	SPI1_ReadWriteByte(W25X_Exit_4_Addres);  
    	W25QXX_CS=1;
    }
    	#endif
    
    void W25QXX_Init(void)
    {
    	
    	//管脚初始化
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    	
    	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
    	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
    	
    	GPIO_Init(GPIOA,&GPIO_InitStructure);
    	W25QXX_CS=1;
    	SPI1_Init();
    	SPI1_SetSpeed(SPI_BaudRatePrescaler_2);
    //进入4字节模式
    	#if	ENABLE_W25Q258
    		W25QXX_Enter_4Byte();
    	#endif
    	W25QXX_TYPE=W25QXX_ReadID();
    }
    
    
    /********************************************************************************
    
    //读取W25QXX的状态寄存器
    //BIT7  6   5   4   3   2   1   0
    //SPR   RV  TB BP2 BP1 BP0 WEL BUSY
    //SPR:默认0,状态寄存器保护位,配合WP使用
    //TB,BP2,BP1,BP0:FLASH区域写保护设置
    //WEL:写使能锁定
    //BUSY:忙标记位(1,忙;0,空闲)
    //默认:0x00   
    
    *******************************************************************************/	
    
    
    u8 W25QXX_ReadSR(void)   
    {  
    	u8 byte=0;   
    	W25QXX_CS=0;                            //使能器件   
    	SPI1_ReadWriteByte(W25X_ReadStatusReg);    //发送读取状态寄存器命令    
    	byte=SPI1_ReadWriteByte(0Xff);             //读取一个字节  
    	W25QXX_CS=1;                            //取消片选     
    	return byte;   
    }
    
    
    /********************************************************************************
    
    //写W25QXX状态寄存器
    //只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! 
    
    *******************************************************************************/	
    
    
    void W25QXX_Write_SR(u8 sr)   
    {   
    	W25QXX_CS=0;                            //使能器件   
    	SPI1_ReadWriteByte(W25X_WriteStatusReg);   //发送写取状态寄存器命令    
    	SPI1_ReadWriteByte(sr);               //写入一个字节  
    	W25QXX_CS=1;                            //取消片选     	      
    } 
    
    /********************************************************************************
    
    //W25QXX写使能	
    //将WEL置位 
    
    *******************************************************************************/
    
      
    void W25QXX_Write_Enable(void)   
    {
    	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_WriteEnable);      //发送写使能  
    	W25QXX_CS=1;                            //取消片选     	      
    } 
    
    /********************************************************************************
    
    //W25QXX写禁止	
    //将WEL清零 
    
    *******************************************************************************/
    
     
    void W25QXX_Write_Disable(void)   
    {  
    	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_WriteDisable);     //发送写禁止指令    
    	W25QXX_CS=1;                            //取消片选     	      
    } 	
    
    /********************************************************************************
    
    //读取芯片ID
    //返回值如下:				   
    //0XEF13,表示芯片型号为W25Q80  
    //0XEF14,表示芯片型号为W25Q16    
    //0XEF15,表示芯片型号为W25Q32  
    //0XEF16,表示芯片型号为W25Q64 
    //0XEF17,表示芯片型号为W25Q128 
    //0XEF18,表示芯片型号为W25Q256 
    *******************************************************************************/
    	  
    u16 W25QXX_ReadID(void)
    {
    	u16 Temp = 0;	  
    	W25QXX_CS=0;				    
    	SPI1_ReadWriteByte(0x90);//发送读取ID命令	    
    	SPI1_ReadWriteByte(0x00); 	    
    	SPI1_ReadWriteByte(0x00); 	    
    	SPI1_ReadWriteByte(0x00); 	 			   
    	Temp|=SPI1_ReadWriteByte(0xFF)<<8;  
    	Temp|=SPI1_ReadWriteByte(0xFF);	 
    	W25QXX_CS=1;				    
    	return Temp;
    }  
    
    /********************************************************************************
    
    //读取SPI FLASH  
    //在指定地址开始读取指定长度的数据
    //pBuffer:数据存储区
    //ReadAddr:开始读取的地址(24bit)(W25Q256为(32bit))
    //NumByteToRead:要读取的字节数(最大65535)
    
    *******************************************************************************/
    
    void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u32 NumByteToRead)   
    { 
     	u32 i;   										    
    	W25QXX_CS=0;                            //使能器件   
    	
    //	SPI1_ReadWriteByte(W25X_ReadData);  
    	#if ENABLE_W25Q258
        SPI1_ReadWriteByte(W25X_ReadData);         //发送4字节地址读取命令   
    		SPI1_ReadWriteByte((u8)((ReadAddr)>>24)); //发送32bit地址
    	#else
    		SPI1_ReadWriteByte(W25X_ReadData);				//发送普通读指令
    	#endif
        SPI1_ReadWriteByte((u8)((ReadAddr)>>16));  //发送24bit地址    
        SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
        SPI1_ReadWriteByte((u8)ReadAddr);   
        for(i=0;i<NumByteToRead;i++)
    	{ 
            pBuffer[i]=SPI1_ReadWriteByte(0XFF);   //循环读数  
        }
    	W25QXX_CS=1;  				    	      
    } 
    
    /********************************************************************************
    
    //SPI在一页(0~65535)内写入少于256个字节的数据
    //在指定地址开始写入最大256字节的数据
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)(W25Q256为(32bit))
    //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	
    
    *******************************************************************************/
     
    void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u32 NumByteToWrite)
    {
     	  u32 i;  
        W25QXX_Write_Enable();                  //SET WEL 
    	  W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_PageProgram);      //发送写页命令  
    	#if ENABLE_W25Q258        //发送读取命令   
    		SPI1_ReadWriteByte((u8)((WriteAddr)>>24)); //发送32bit地址
    	#endif
        SPI1_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址    
        SPI1_ReadWriteByte((u8)((WriteAddr)>>8));   
        SPI1_ReadWriteByte((u8)WriteAddr);   
        for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer[i]);//循环写数  
    	  W25QXX_CS=1;                            //取消片选 
    	  W25QXX_Wait_Busy();					   //等待写入结束
    } 
    
    
    /********************************************************************************
    
    //无检验写SPI FLASH 
    //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
    //具有自动换页功能 
    //在指定地址开始写入指定长度的数据,但是要确保地址不越界!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)(W25Q256为(32bit))
    //NumByteToWrite:要写入的字节数(最大65535)
    //CHECK OK
    
    *******************************************************************************/
    
    void W25QXX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u32 NumByteToWrite)   
    { 			 		 
    	u32 pageremain;	   
    	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
    	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
    	while(1)
    	{	   
    		W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
    		if(NumByteToWrite==pageremain)break;//写入结束了
    	 	else //NumByteToWrite>pageremain
    		{
    			pBuffer+=pageremain;
    			WriteAddr+=pageremain;	
    
    			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
    			if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
    			else pageremain=NumByteToWrite; 	  //不够256个字节了
    		}
    	};	    
    } 
    
    
    /********************************************************************************
    
    //写SPI FLASH  
    //在指定地址开始写入指定长度的数据
    //该函数带擦除操作!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)(W25Q256为(32bit))						
    //NumByteToWrite:要写入的字节数(最大65535) 
    
    *******************************************************************************/
    
      
    u8 W25QXX_BUFFER[4096];		
    
    void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u32 NumByteToWrite)   
    { 
    	u32 secpos;
    	u32 secoff;
    	u32 secremain;	   
     	u32 i;    
    	u8 * W25QXX_BUF;
    	
      W25QXX_BUF=W25QXX_BUFFER;	     
     	secpos=WriteAddr/4096;//扇区地址  
    	secoff=WriteAddr%4096;//在扇区内的偏移
    	secremain=4096-secoff;//扇区剩余空间大小   
     	//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
     	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
    	while(1) 
    	{	
    		W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
    		for(i=0;i<secremain;i++)//校验数据
    		{
    			if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除  	  
    		}
    		if(i<secremain)//需要擦除
    		{
    			W25QXX_Erase_Sector(secpos);//擦除这个扇区
    			for(i=0;i<secremain;i++)	   //复制
    			{
    				W25QXX_BUF[i+secoff]=pBuffer[i];	  
    			}
    			W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  
    
    		}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
    		if(NumByteToWrite==secremain)break;//写入结束了
    		else//写入未结束
    		{
    			secpos++;//扇区地址增1
    			secoff=0;//偏移位置为0 	 
    
    		   	pBuffer+=secremain;  //指针偏移
    			WriteAddr+=secremain;//写地址偏移	   
    		   	NumByteToWrite-=secremain;				//字节数递减
    			if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完
    			else secremain=NumByteToWrite;			//下一个扇区可以写完了
    		}	 
    	};	 
    }
    
    
    /********************************************************************************
    
    //擦除整个芯片		  
    //等待时间超长...
    
    *******************************************************************************/
    
    
    void W25QXX_Erase_Chip(void)   
    {                                   
        W25QXX_Write_Enable();                  //SET WEL 
        W25QXX_Wait_Busy();   
      	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_ChipErase);     //发送片擦除命令  
    	  W25QXX_CS=1;                            //取消片选     	      
    	  W25QXX_Wait_Busy();   				  			  //等待芯片擦除结束
    } 
    
    
    /********************************************************************************
    
    //擦除一个扇区
    //Dst_Addr:扇区地址 根据实际容量设置
    //擦除一个山区的最少时间:150ms
    
    *******************************************************************************/
    
    
    void W25QXX_Erase_Sector(u32 Dst_Addr)   
    {  
    	//监视falsh擦除情况,测试用   
     	  //printf("fe:%x\r\n",Dst_Addr);	  
     	  Dst_Addr*=4096;
        W25QXX_Write_Enable();                  //SET WEL 	 
        W25QXX_Wait_Busy();   
      	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_SectorErase);      //发送扇区擦除指令 
    	#if ENABLE_W25Q258        //发送读取命令   
    		SPI1_ReadWriteByte((u8)((Dst_Addr)>>24)); 
    	#endif
        SPI1_ReadWriteByte((u8)((Dst_Addr)>>16));  //发送24bit地址    
        SPI1_ReadWriteByte((u8)((Dst_Addr)>>8));   
        SPI1_ReadWriteByte((u8)Dst_Addr);  
    	  W25QXX_CS=1;                            //取消片选     	      
        W25QXX_Wait_Busy();   				   //等待擦除完成
    }
    
    /********************************************************************************
    
    //等待空闲
    
    *******************************************************************************/
    
    void W25QXX_Wait_Busy(void)   
    {   
    	while((W25QXX_ReadSR()&0x01)==0x01);   // 等待BUSY位清空
    }
    
    /********************************************************************************
    
    //进入掉电模式
    
    *******************************************************************************/
    
    void W25QXX_PowerDown(void)   
    { 
    	  u16 Time_i=0xffff;
    	
      	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_PowerDown);        //发送掉电命令  
    	  W25QXX_CS=1;                            //取消片选     	      
        while(Time_i--);                               //等待TPD  
    }  
    
    /********************************************************************************
    
    //唤醒
    
    *******************************************************************************/
    
    
    void W25QXX_WAKEUP(void)   
    {  
    	  u16 Time_i=0xffff;
      	W25QXX_CS=0;                            //使能器件   
        SPI1_ReadWriteByte(W25X_ReleasePowerDown);   //  send W25X_PowerDown command 0xAB    
    	  W25QXX_CS=1;                            //取消片选     	      
        while(Time_i--);                               //等待TRES1
    }   
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    对于4字节读取时,根据芯片手册,使用Read_Data(03h)也可以访问4字节地址,测试后也确实可以

    当然 也可以使用专门的4地址读指令Read_Date_with_4_Byte_Address(13h)

    这里我使用的是Read_Date_with_4_Byte_Address(13h)

    void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u32 NumByteToRead)   
    { 
     	u32 i;   										    
    	W25QXX_CS=0;                            //使能器件   
    	
    //	SPI1_ReadWriteByte(W25X_ReadData);  
    	#if ENABLE_W25Q258
        SPI1_ReadWriteByte(W25X_ReadData);         //发送4字节地址读取命令   
    		SPI1_ReadWriteByte((u8)((ReadAddr)>>24)); //发送32bit地址
    	#else
    		SPI1_ReadWriteByte(W25X_ReadData);				//发送普通读指令
    	#endif
        SPI1_ReadWriteByte((u8)((ReadAddr)>>16));  //发送24bit地址    
        SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
        SPI1_ReadWriteByte((u8)ReadAddr);   
        for(i=0;i<NumByteToRead;i++)
    	{ 
            pBuffer[i]=SPI1_ReadWriteByte(0XFF);   //循环读数  
        }
    	W25QXX_CS=1;  				    	      
    } 

    更多相关内容
  • 1. W25Q80 (8M-bit)、W25Q16 (16M-bit)和W25Q32 (32M-bit)串行闪存为空间、引脚和电源有限的系统提供了存储解决方案。25Q系列提供的灵活性和性能远远超过普通的串行闪存设备。他们是理想的代码隐藏到RAM,执行代码...
  • 华邦 W25Q80 数据手册

    2018-05-28 18:27:25
    华邦 W25Q80英文版数据手册,注意是英文版,是英文版!
  • W25Q80NA.zip

    2019-10-15 21:06:56
    W25Q80NA Verilog仿真模型用于QSPI/SPI外设的仿真和调试。
  • W25Q80_datasheet.pdf

    2019-11-08 11:13:14
    W25Q80 SPI FLASH系列的文档,很详细哦 好用哦多看看哦
  • 基于W25Q80BL的FPGA配置控制器的设计与验证.pdf
  • W25Q80BV是台湾华邦电子(Winbond)生产的8M-bit串行flash芯片。主要特性有: 工作电压:2.5 ~ 3.6 V 功耗:读写(active)时4mA,低功耗(power-down)时<1μA 容量:8M-bit/1M-byte,包含4096个页(每页大小...

    W25Q80BV是台湾华邦电子(Winbond)生产的8M-bit串行flash芯片。主要特性有:

    • 工作电压:2.5 ~ 3.6 V
    • 功耗:读写(active)时4mA,低功耗(power-down)时<1μA
    • 容量:8M-bit/1M-byte,包含4096个页(每页大小256字节)
    • 接口:Standard/Dual/Quad SPI,支持时钟频率最高104MHz
    • 支持以4/32/64k-bytes为单位进行Sector/Block擦除
    • 一次写入最多256字节
    • 软件/硬件写保护功能
    • 大于10万次擦除/编程寿命
    • 大于20年的数据保存时间
    • 封装:SOIC/USON/WSON/PDIP

    管脚定义
    在这里插入图片描述
    在这里插入图片描述

    与Arduino的连接
    采用工作于3.3V的Pro Mini版本进行简单调试,接法如下。

    在这里插入图片描述
    其中HOLD脚须上拉接到3.3V,否则器件无法正常工作;WP脚可以浮空。

    W25Q80BV Pro Mini (3.3V/8MHz)

    VCC <------> 3.3V

    GND <------> GND

    /CS <------> SS (D10)

    DI <------> MOSI (D11)

    DO <------> MISO (D12)

    CLK <------> SCK (D13)

    功能调试

    1. 与I2C不同,利用SPI库操作时,读和写都用同一个函数SPI.transfer()实现。

    2. 读取时,可以任意地址、任意长度进行读取。

    3. 与EEPROM不同,SPI Flash写入前,需要对写入的存储空间进行擦除(Erase)操作,否则写入不成功。芯片支持Chip Erase(整片擦除)、Block Erase(32K bytes/64K bytes块擦除)和Sector Erase(4K bytes扇区擦除)。

    4. 当写操作对应的地址空间到达page的边界,再继续写入时目的地址会自动roll over到本页的起始位置。

    测试代码

      1 /*
      2     communication with W25Q80BV (1 MBYTE SPI FLASH) using Arduino Pro Mini 3.3V/8MHz
      3     Reference: http://www.instructables.com/id/How-to-Design-with-Discrete-SPI-Flash-Memory/?ALLSTEPS
      4 */
      5 
      6 // the SPI bus uses pins 10 (SS), 11 (MOSI), 12 (MISO), and 13 (SCK)
      7 
      8 #include <SPI.h>
      9 
     10 #define READ_JEDEC_ID 0x9F
     11 #define READ_STATUS_1 0x05
     12 #define READ_DATA 0x03
     13 #define WRITE_ENABLE 0x06
     14 #define PAGE_PROGRAM 0x02
     15 #define CHIP_ERASE 0xC7
     16 
     17 byte pageBuffer[256];
     18 char str[] = "An apple a day keeps the doctor away."; //short than 256
     19 
     20 void setup()
     21 {
     22     SPI.begin();
     23     SPI.setDataMode(SPI_MODE0);
     24     SPI.setBitOrder(MSBFIRST);
     25     Serial.begin(9600);
     26 
     27     ReadID();
     28     EraseChip();
     29     WritePage(0x1234, str, sizeof(str));
     30 }
     31 
     32 void loop()
     33 {
     34     ReadPage(0x1234, pageBuffer, sizeof(str));
     35 
     36     for(int i = 0; i < sizeof(str); i++)
     37     {
     38         Serial.print(char(pageBuffer[i]));
     39     }
     40     Serial.println();
     41 
     42     delay(2000);
     43 }
     44 
     45 void CheckBusy()
     46 {
     47     digitalWrite(SS, HIGH);
     48     digitalWrite(SS, LOW);
     49     SPI.transfer(READ_STATUS_1);
     50     while(SPI.transfer(0) & 0x01); 
     51     digitalWrite(SS, HIGH);
     52 }
     53 
     54 void ReadID()
     55 {
     56     digitalWrite(SS, HIGH);
     57     digitalWrite(SS, LOW);
     58     SPI.transfer(READ_JEDEC_ID);
     59     byte manuID = SPI.transfer(0);
     60     byte memoType = SPI.transfer(0);
     61     byte capa = SPI.transfer(0);
     62     digitalWrite(SS, HIGH);
     63 
     64     Serial.print("Manufacturer ID: "); Serial.println(manuID, HEX);
     65     Serial.print("Memory Type: "); Serial.println(memoType, HEX);
     66     Serial.print("Capacity : "); Serial.println(capa, HEX);
     67 
     68     CheckBusy();
     69 }
     70 
     71 void ReadPage(word pageNumber, byte pageBuffer[], int length) 
     72 {
     73     // pageNumber: 16-bit data
     74     digitalWrite(SS, HIGH);
     75     digitalWrite(SS, LOW);
     76     SPI.transfer(READ_DATA);
     77     SPI.transfer((pageNumber >> 8) & 0xFF);
     78     SPI.transfer(pageNumber & 0xFF);
     79     SPI.transfer(0);
     80     for(int i = 0; i < length; i++)
     81     {
     82         pageBuffer[i] = SPI.transfer(0);
     83     }
     84     digitalWrite(SS, HIGH);
     85     CheckBusy();
     86 }
     87 
     88 void WritePage(word pageNumber, char pageBuffer[], int length) 
     89 {
     90     digitalWrite(SS, HIGH);
     91     digitalWrite(SS, LOW);  
     92     SPI.transfer(WRITE_ENABLE);
     93     digitalWrite(SS, HIGH);
     94     digitalWrite(SS, LOW);  
     95     SPI.transfer(PAGE_PROGRAM);
     96     SPI.transfer((pageNumber >>  8) & 0xFF);
     97     SPI.transfer(pageNumber & 0xFF);
     98     SPI.transfer(0);
     99     for(int i = 0; i < length; i++)
    100     {
    101         SPI.transfer(byte(pageBuffer[i]));
    102     }
    103     digitalWrite(SS, HIGH);
    104     CheckBusy();
    105 }
    106 
    107 void EraseChip()
    108 {
    109     digitalWrite(SS, HIGH);
    110     digitalWrite(SS, LOW);  
    111     SPI.transfer(WRITE_ENABLE);
    112     digitalWrite(SS, HIGH);
    113     digitalWrite(SS, LOW);  
    114     SPI.transfer(CHIP_ERASE);
    115     digitalWrite(SS, HIGH);
    116     CheckBusy();
    117 }
    

    View Code
    读取芯片的ID信息,向W25Q80BV写入一段字符串,再将写入的信息反复读出:
    在这里插入图片描述
    参考资料
    W25Q80BV datasheet - Winbond
    Arduino - SPI
    Designing with Discrete SPI Flash Memory - Instructables
    Flash芯片硬件特性

    转载于:https://www.cnblogs.com/zlbg/p/4246721.html

    展开全文
  • 最近使用STM32的QSPI驱动W25QXX系列Flash时遇到的一个现象:原子的例程,同样的程序驱动W25Q16JVSIQ没有任何问题,但是驱动W25Q80DVSIG的时候读不到芯片ID,读写数据也都不成功。 问题排查 于是网上搜索了很多相关的...

    问题描述

    最近使用STM32的QSPI驱动W25QXX系列Flash时遇到的一个现象:原子的例程,同样的程序驱动W25Q16JVSIQ没有任何问题,但是驱动W25Q80DVSIG的时候读不到芯片ID,读写数据也都不成功。

    问题排查

    于是网上搜索了很多相关的问题,确定大概的方向:W25Q80DVSIG上状态寄存器2的QE位没有置1导致,而W25Q16JVSIQ出厂时默认QE位已经置1(也许后缀为Q的型号就是QE出厂置1的意思,未验证,但手册上有提及)
    后缀为"IG"的型号出厂默认QE位为0
    在这里插入图片描述

    既然出厂时没有帮我们把QE位置1,那我们就自己将它置1就好了。步骤也不难,无非就是先把状态寄存器的写保护位WEL置1,关掉写保护,再把状态寄存器2读出来,读出来的值第2位 置1后再写回状态寄存器2就行了。但问题就在于,原子的例程里初始化FLASH的时候已经有将QE位 置1的代码了。。。在这里插入图片描述

    问题解决

    经过调试以及研读芯片手册,发现问题所在。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    以上几张图是原子例程参照W25Q32(或其他型号)手册写的指令表,这没什么问题,当我找到W25Q80DV芯片手册的指令表时,问题就突显出来了。
    在这里插入图片描述
    W25Q80DV的写入状态寄存器指令只有一条:“0x01”,而W25Q32JV(或其他大部分型号)不同状态寄存器的写入指令是不同的(01h/31h)。W25Q80DV是一条指令就把状态寄存器1和2一起写入:“01h S7-S0 S15-S8”,指令后的第一个字节是状态寄存器1的写入值,第二个字节是状态寄存器2的写入值。所以只要稍微修改一下程序就可以用了,修改如下:
    在这里插入图片描述
    在这里插入图片描述
    以上就是这次QSPI驱动W25Q80不成功的问题记录以及解决方法,如果有疑问或者有不同见解的朋友欢迎评论区一起交流!

    展开全文
  • W25Q80和GD25Q80

    万次阅读 2018-09-29 15:45:22
    W25Q80: 8M-bit 1024KB  80MHz clock operation 共有16个Block,每个Block有16个扇区,每个扇区4KB,每一页256个字节 每个设备有64位唯一ID GD25Q80: 8M-bit 1024KB  120MHz 快速阅读 共有16个Block,...

    二者同为SPI-Flash,前者为华邦公司产品,后者是GD公司产品。

    W25Q80:

    • 8M-bit  1024KB  
    • 80MHz clock operation
    • 共有16个Block,每个Block有16个扇区,每个扇区4KB,每一页256个字节
    • 每个设备有64位唯一ID

    GD25Q80:

    • 8M-bit  1024KB  
    • 120MHz 快速阅读
    • 共有16个Block,每个Block有16个扇区,每个扇区4KB,每一页256个字节
    • 每个设备有128位唯一ID

    引脚:(二者引脚完全兼容)

    寄存器:

    W25Q80 状态寄存器(S15~S0)

    BUSY:FLASH正在擦除或者正在写入

    TB:Top/Bottom写保护位,与BP[2:0]构成更多组合

    SEC:扇区保护位,与BP[2:0]构成更多组合

    SRP0:状态寄存器保护位

    这5位决定写保护的范围

    GD25Q80 状态寄存器(S15~S0)

    SUS:只读位,该位在擦除、编程、暂停指令后置1 个人感觉这位没什么用

    CMP:与BP[4:0]构成更多的组合 默认置0,与W25q80保持兼容

    HPM:该位置1表示FLASH当前是高性能模式 一般不用

    LB:OTP位,写1,安全寄存器变为永久只读 一般不用

    这6位决定写保护范围,其实除了S14,剩下的和W25Q80寄存器是一样的,都是S2~S6共5位

    那么S14是什么东西呢?上文讲了,S14即CMP,CMP=0或1 时 只是保护的范围不同罢了

    比如当CMP=0,S6~S2= 00010 时 写保护区域为  0E0000H-0FFFFFH 128KB(与W25Q80一样)

    CMP=1时,S6~S2=00010时  写保护区域为   000000H-0DFFFFH 896KB

    默认CMP=0,即与W25Q80保持兼容。

    指令表:

    以下指令二者是一样的,实际上GD32Q80多了很多指令,比如和安全寄存器相关的编程,擦除,读取三条指令,但是通常我们也只会用到以下指令。

    #define W25X_WriteEnable		0x06 
    #define W25X_WriteDisable		0x04 
    #define W25X_ReadStatusReg		0x05 
    #define W25X_WriteStatusReg		0x01 
    #define W25X_ReadData			0x03 
    #define W25X_FastReadData		0x0B 
    #define W25X_FastReadDual		0x3B 
    #define W25X_PageProgram		0x02 
    #define W25X_BlockErase			0xD8 
    #define W25X_SectorErase		0x20 
    #define W25X_ChipErase			0xC7 
    #define W25X_PowerDown			0xB9 
    #define W25X_ReleasePowerDown	0xAB 
    #define W25X_DeviceID			0xAB 
    #define W25X_ManufactDeviceID	0x90 
    #define W25X_JedecDeviceID		0x9F 

    值得注意的是,二者厂商的ID和设备ID是不同的,原子例程有个死循环验证厂商和设备ID,如果用的是GD25系列的Flash需要改下相关宏定义。

    华邦的厂商和设备ID(不是芯片唯一ID)一般是 0xEFXX,GD是0xC8XX(XX由不同容量决定)。

     

    综上所述,二者可以互相替换。

     

    展开全文
  • 华邦存储器W25Q80, W25Q16, W25Q32系列与stm32f1系列单片机的spi通讯 2020.4.9 spi通讯在配置好之后一定要开启spi使能,和串口的配置是一样的 2020.4.13 华邦存储器的spi通讯调试完成。 总结,在调试的过程中出现了...
  • 本文只对 W25Q80DV 数据手册的一部分进行解读,其涵盖的内容基本足够开发标准 SPI 接口的 Linux 驱动和裸板驱动。完整的 Datasheet 下载:  https://download.csdn.net/download/luckydarcy/10443182 一般描述 ...
  • Linux 驱动 SPI Flash(W25Q80DV)

    万次阅读 2018-06-13 19:21:27
    W25Q80DV 是 Winbond 的一款 SPI Flash,容量大小为 8M bit。如果还没看 W25Q80DV 的数据手册,赶紧去看!  https://blog.csdn.net/lu_embedded/article/details/80682374  本文描述的是在 i.MX6q 硬件平台上...
  • w25q80dv 英文手册..

    2022-03-21 11:43:36
    w25q80dv 手册
  • DS1302N DS2460 RS232 RS485 CH340G W25Q80B ALTIUM原理图库封装库(AD集成库)39个合集,PcbLib+SchLib格式,Altium Designer原理图库+PCB封装库, Library Component Count : 39 Name Description ---------------...
  • Flash_W25Q80数据手册.pdf

    2021-11-05 17:16:39
    Flash_W25Q80数据手册
  • W25Q80源代码

    2013-04-17 22:31:03
    通过产品测试,运行稳定数据手册W25Q80_IcpdfCom_207315.pdf
  • W25Q80NE verilog Model

    2018-01-17 15:59:06
    W25Q80NE verilog Model SPI Flash 仿真模型,verilog 仿真模型,SPI端口,支持多种读写操作操作
  • NRF52832与W25Q80通信

    2019-03-30 21:15:00
    void W25Q80_FLASH_PageWrite(unsigned char* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { W25Q80_WriteEnable(); //发送FLASH写使能命令 nrf_gpio_pin_clear(SPI_SS_PIN); //片选有效 W25Q80_...
  • w25q128 verilog仿真模型

    2019-04-23 16:22:11
    w25q128 官方verilog仿真模型,有助于开发QSPI外设IP,用于QSPI/SPI外设的仿真和调试。
  • [学习笔记]STM32F1软件SPI读写W25Qx源码(寄存器、标准库、HAL库)
  • 一、W25Q简介 W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb。该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件。W25Q64将8M字节的容量分为128个块,每个块大小为64K字节,每个块又分为16...
  • LPCOpen-keil-lpc43xx 适用于LPC43xx的NXP LPCOpen,将Keil移植到Micromint Bambino。 恩智浦LPCOpen平台提供了使用恩智浦微控制器及其外围设备的启动代码,设备驱动程序和代码示例。 通用API可以与所有NXP ARM ...
  • W25Q16BV中文数据手册

    2016-01-19 13:52:57
    最新的W25Q16BV闪存中文数据手册(W25Q16BV(16M位)串行闪存,该W25Q16BV阵列是由每256字节可编程8,192页.最多256个字节,2.7到3.6V电源)
  • w25q64中文数据手册

    热门讨论 2016-01-09 16:03:39
    W25Q80(8M-bit),W25Q16(16M-bit)和W25Q32(32M-bit)是为系统提供一个最小的空间、引脚和功耗的存储器解决方案的串行Flash存储器。25Q系列比普通的串行Flash存储器更灵活,性能更优越。基于双倍/四倍的SPI,它们能够...
  • 本文仅仅记录使用RTT的QSPI总线设备驱动W25Q
  • } else { /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */ rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);//先发送后接收数据id rt_kprintf("use rt_qspi_send_then_recv() read w25q ...
  • STM32cubeide/STM32cubeMX USB链接W25QXX做U盘,使用HAL库
  • CC2640R2F BLE5.0 CC2640R2F SPI驱动实现

    千次阅读 2017-08-07 09:58:45
    SPI驱动 这一节我们详细讲解TI CC13x0/CC26x0 SDK开发平台 基于TI-RTOS的SPI驱动实现,主要了解SPI驱动的分层实现、驱动接口,以及结合开发板板载SPIFlash调试通过驱动。 概述 ...SPI(Serial Perripheral ...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 323
精华内容 129
关键字:

w25q80

友情链接: ccode.rar