芯查查logo
  • 数据服务
    1. 新产品
    2. 物料选型
    3. 查替代
    4. 丝印反查
    5. 查品牌
    6. PCN/PDN
    7. 查方案
    8. 查代理
    9. 数据合作
  • SaaS/方案
      SaaS产品
    1. 供应链波动监控
    2. 半导体产业链地图
    3. BOM管理
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 行业资讯
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
  • 开通会员
【星允派 NEBULA PI】08硬件SPI驱动W25Q64
原创 发布时间:昨天 20:28
版块:
单片机/MCU论坛
简介:硬件调试SPI过程

一:W25Q64芯片介绍:

 W25Q64 是一款常见的串行 Flash 存储器芯片,由华邦(Winbond)公司生产。它的存储容量为 64Mb(8MB),采用 SPI(串行外设接口)进行通信,常用于嵌入式系统中存储代码或数据。

二:W25Q64操作注意事项:

W25Q64 的基本操作遵循 SPI 协议,一般流程是:片选拉低 → 发送命令字 → 发送地址(如需)→ 交换数据 → 片选拉高。

2.1:写使能(Write Enable, 06h):在执行任何编程或擦除操作前,必须先发送写使能指令。该指令会将状态寄存器中的写使能锁存(WEL)

2.2:页编程(Page Program, 02h):向指定地址写入数据。一次最多写入256字节(一页),且不能跨页写入。如果写入数据地址会跨页,超出页首地址部分会从当前页的开头覆写8。写入前必须确保目标区域已被擦除。

2.3:扇区擦除(Sector Erase, 20h):擦除指定4KB扇区。擦除操作会将所有位变为1。擦除前需写使能。

2.4:块擦除(Block Erase):提供32KB (52h) 和64KB (D8h) 块擦除选项。

2.5:芯片擦除(Chip Erase, C7h / 60h):擦除整个芯片。谨慎使用。

2.6:读数据(Read Data, 03h):从指定地址开始读取数据。读取操作没有页的限制8。

2.7:读状态寄存器(Read Status Register, 05h):主要用于检查 BUSY 位(S0)和 WEL 位(S1)。在编程、擦除或写状态寄存器期间,BUSY位会置1,此时芯片仅响应读状态寄存器和擦除暂停等少数指令。

读设备ID:如 Read JEDEC ID (9Fh) 可用于识别器件

三:STM32cube MX 软件配置过程:

四:软件代码编程:

重新定义一下SPI发送字节的函数:

uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
    uint8_t Rxdata;
    HAL_SPI_TransmitReceive(&hspi1,&TxData,&Rxdata,1, HAL_MAX_DELAY);       
 	return Rxdata;          		    //返回收到的数据		
}

4.1 检测有无W25Q芯片

/*******************************************************************************
* Function Name  : void WriteBufferTo24C02(int addr,uint8_t *pdata,char length)
* Description    : 
* Input          : 
* Output         : None
* Return         : None
*******************************************************************************/
void W25QXX_Init(void)
{ 
    uint8_t temp;
    __HAL_RCC_GPIOB_CLK_ENABLE();           //使能GPIOB时钟
    
	  W25QXX_TYPE=W25QXX_ReadID();	        //读取FLASH ID.
    if(W25QXX_TYPE==W25Q256)                //SPI FLASH为W25Q256
    {
        temp=W25QXX_ReadSR(3);              //读取状态寄存器3,判断地址模式
        if((temp&0X01)==0)			        //如果不是4字节地址模式,则进入4字节地址模式
		{
			FLASH_CS_LOW() ; 			        //选中
			SPI1_ReadWriteByte(W25X_Enable4ByteAddr);//发送进入4字节地址模式指令   
			FLASH_CS_HIGH();;       		        //取消片选   
		}
    }
}

4.2 写入数据

void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
 	uint16_t i;  
    W25QXX_Write_Enable();                  //SET WEL 
	FLASH_CS_LOW() ;                             //使能器件   
    SPI1_ReadWriteByte(W25X_PageProgram);   //发送写页命令   
    if(W25QXX_TYPE==W25Q256)                //如果是W25Q64的话地址为4字节的,要发送最高8位
    {
        SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>24)); 
    }
    SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址    
    SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>8));   
    SPI1_ReadWriteByte((uint8_t)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer[i]);//循环写数  
		FLASH_CS_HIGH();;	                            //取消片选 
	W25QXX_Wait_Busy();					   //等待写入结束
} 

4.3 读取数据

void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)   
{ 
 	uint16_t i;   										    
	FLASH_CS_LOW() ;                           //使能器件   
    SPI1_ReadWriteByte(W25X_ReadData);      //发送读取命令  
    if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
    {
        SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>24));    
    }
    SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>16));   //发送24bit地址    
    SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>8));   
    SPI1_ReadWriteByte((uint8_t)ReadAddr);   
    for(i=0;i<NumByteToRead;i++)
	{ 
        pBuffer[i]=SPI1_ReadWriteByte(0XFF);    //循环读数  
    }
		FLASH_CS_HIGH();;	  				    	      
} 

4.4 测试程序:

void Test_SPI_Funtion(void)
{

	WriteBuffer24C02[0]= 0xFA ;
	WriteBuffer24C02[1]= 0xFB ;
	WriteBuffer24C02[2]= 0xFC ;
	WriteBuffer24C02[3]= 0x05 ;
	WriteBuffer24C02[4]= 0xC0 ;
	WriteBuffer24C02[5]= 0x01 ;
	WriteBuffer24C02[6]= 0x02 ;

	W25QXX_Write(&WriteBuffer24C02[0],0,7);
  HAL_Delay(20);
  W25QXX_Read(&ReadBuffer24C02[0],0,7) ;

  HAL_UART_Transmit(&huart1, &ReadBuffer24C02[0], 7, 100); 

}

当然为了快速验证,将之前操作24C02的buffer 写入到W25Q64里面,然后通过串口输出。

五:验证如下:

六:一些调试SPI的心得如下:

SPI通信中的时钟极性(CPOL)和时钟相位(CPHA)是两个关键参数。它们定义了时钟信号在空闲状态下的电平和数据采样的时机。当时是利用硬件的SPI读取两个芯片,一个是存储芯片(W25Q64),一个是AD芯片(CS5530),由于这个两个芯片的时序不一致,一个是在上升沿读取数据,另外一个是在下降沿读取数据,当时也是调试好久才发现,时序不一致,当初也是刚毕业不久,也没有太多的工作经验,还以为是芯片损坏,现在想起来还是真的小白了。后来工作时间久了才发现,影响SPI通讯不正常的原因有很多,需要注意硬件连接、通信协议与时序、数据传输等方面。

就是在调试这两款SPI从机的时候,当时为了减少硬件的引脚,从而将省出的引脚复用其他的功能,从而导致了自己在软件调试时候遇到了不小的麻烦。当时都使用逻辑分析仪一点点的查出来的。

申请原创奖励
昨天 20:28
  • 举报
😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷😸😹😺😻😼😽😾😿🙀🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏✂✅✈✉✊✋✌✏✒✔✖✨✳✴❄❇❌❎❓❔❕❗❤➕➖➗➡➰🚀🚃🚄🚅🚇🚉🚌🚏🚑🚒🚓🚕🚗🚙🚚🚢🚤🚥🚧🚨🚩🚪🚫🚬🚭🚲🚶🚹🚺🚻🚼🚽🚾🛀Ⓜ🅰🅱🅾🅿🆎🆑🆒🆓🆔🆕
@好友

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
发布者
聪聪哥哥
最新帖子
【星允派 NEBULA PI】09:USB虚拟CDC与串口1【星允派 NEBULA PI】08硬件SPI驱动W25Q64【星允派 NEBULA PI】07:IIC驱动24C02【星允派 NEBULA PI】05:调试外部中断【星允派 NEBULA PI】04:DMA+空闲中断收发数据
热门版块
查看更多
问型号
问技术
问行情
电子DIY
汽车电子工程师论坛
工业电子专区
新手入门指南
单片机/MCU论坛
PCB设计
开源项目

19

收藏

分享

微信扫码
分享给好友

评论