当前位置: 首页 > article >正文

HAL库W25Qxx系列芯片驱动

bsp_w25q64.h:
#ifndef __W25Qxx_H
#define __W25Qxx_H
 
/* Includes ------------------------------------------------------------------*/


/***** W25Q128 单位字节*****/
#define W25Q128FV_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */
#define W25Q128FV_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
#define W25Q128FV_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */
#define W25Q128FV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */
 
#define W25Q128FV_DUMMY_CYCLES_READ           4
#define W25Q128FV_DUMMY_CYCLES_READ_QUAD      10
 
#define W25Q128FV_BULK_ERASE_MAX_TIME         250000
#define W25Q128FV_SECTOR_ERASE_MAX_TIME       3000
#define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME    800


/***** W25Q64 单位字节*****/
#define W25Q64FV_FLASH_SIZE                  0x800000 /* 64 MBits => 8MBytes */
#define W25Q64FV_SECTOR_SIZE                 0x10000   /* 128 sectors of 64KBytes */
#define W25Q64FV_SUBSECTOR_SIZE              0x1000    /* 2048 subsectors of 4kBytes */
#define W25Q64FV_SUBSECTOR_NUM               0x800 
#define W25Q64FV_PAGE_SIZE                   0x100     /* 32768 pages of 256 bytes */

#define W25Q64_FLASH_ID        0xEF16

#define W25Qx_TIMEOUT_VALUE 1000
 
/* Reset Operations */
#define RESET_ENABLE_CMD                     0x66
#define RESET_MEMORY_CMD                     0x99
 
#define ENTER_QPI_MODE_CMD                   0x38
#define EXIT_QPI_MODE_CMD                    0xFF
 
/* Identification Operations */
#define READ_ID_CMD                          0x90
#define DUAL_READ_ID_CMD                     0x92
#define QUAD_READ_ID_CMD                     0x94
#define READ_JEDEC_ID_CMD                    0x9F
 
/* Read Operations */
#define READ_CMD                             0x03
#define FAST_READ_CMD                        0x0B
#define DUAL_OUT_FAST_READ_CMD               0x3B
#define DUAL_INOUT_FAST_READ_CMD             0xBB
#define QUAD_OUT_FAST_READ_CMD               0x6B
#define QUAD_INOUT_FAST_READ_CMD             0xEB
 
/* Write Operations */
#define WRITE_ENABLE_CMD                     0x06
#define WRITE_DISABLE_CMD                    0x04
 
/* Register Operations */
#define READ_STATUS_REG1_CMD                  0x05
#define READ_STATUS_REG2_CMD                  0x35
#define READ_STATUS_REG3_CMD                  0x15
 
#define WRITE_STATUS_REG1_CMD                 0x01
#define WRITE_STATUS_REG2_CMD                 0x31
#define WRITE_STATUS_REG3_CMD                 0x11
 
 
/* Program Operations */
#define PAGE_PROG_CMD                        0x02
#define QUAD_INPUT_PAGE_PROG_CMD             0x32
 
 
/* Erase Operations */
#define SECTOR_ERASE_CMD                     0x20
#define CHIP_ERASE_CMD                       0xC7
 
#define PROG_ERASE_RESUME_CMD                0x7A
#define PROG_ERASE_SUSPEND_CMD               0x75
 
 
/* Flag Status Register */
#define W25Q128FV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */
#define W25Q128FV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable */
#define W25Q128FV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */
 

#define W25QX_SPI_Handler  &hspi2
#define W25QX_SPI  SPI2
#define USE_DMA    1   //目前实现不了DMA读写,会出错
#define W25Qx_Enable() 			HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET)
#define W25Qx_Disable() 		HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET)
 
#define W25Qx_OK            ((uint8_t)0x00)
#define W25Qx_ERROR         ((uint8_t)0x01)
#define W25Qx_BUSY          ((uint8_t)0x02)
#define W25Qx_TIMEOUT		((uint8_t)0x03)
 
 
uint8_t BSP_W25Qx_Init(void);
static void	BSP_W25Qx_Reset(void);
static uint8_t BSP_W25Qx_GetStatus(void);
uint8_t BSP_W25Qx_WriteEnable(void);
void BSP_W25Qx_Read_ID(uint8_t *ID);
uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);
uint8_t BSP_W25Qx_Erase_Chip(void);
void BSP_W25QX_Test(void);
 
#endif 
 



bsp_w25q64.c:
#include "bsp_W25q64.h"

 /**********************************************************************************
  * 函数功能: 模块初始化
  */
uint8_t BSP_W25Qx_Init(void)
{ 	
	BSP_W25Qx_Reset();	
	return BSP_W25Qx_GetStatus();
}
 
 
static void	BSP_W25Qx_Reset(void)
{
	uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
	
	W25Qx_Enable();
	/* Send the reset command */
	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 2, W25Qx_TIMEOUT_VALUE);	

	W25Qx_Disable();
 
}
 
 /**********************************************************************************
  * 函数功能: 获取设备状态
  */
static uint8_t BSP_W25Qx_GetStatus(void)
{
	uint8_t cmd[] = {READ_STATUS_REG1_CMD};
	uint8_t status;
	
	W25Qx_Enable();

	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 1, W25Qx_TIMEOUT_VALUE);	
	HAL_SPI_Receive(W25QX_SPI_Handler,&status, 1, W25Qx_TIMEOUT_VALUE);	


	W25Qx_Disable();
	
	/* Check the value of the register */
  if((status & W25Q128FV_FSR_BUSY) != 0)
  {
    return W25Qx_BUSY;
  }
	else
	{
		return W25Qx_OK;
	}		
}
 
 /**********************************************************************************
  * 函数功能: 写使能
  */
uint8_t BSP_W25Qx_WriteEnable(void)
{
	uint8_t cmd[] = {WRITE_ENABLE_CMD};
	uint32_t tickstart = HAL_GetTick();
 
	/*Select the FLASH: Chip Select low */
	W25Qx_Enable();
	/* Send the read ID command */
	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 1, W25Qx_TIMEOUT_VALUE);	
	
	/*Deselect the FLASH: Chip Select high */
	W25Qx_Disable();
	
	/* Wait the end of Flash writing */
	while(BSP_W25Qx_GetStatus() == W25Qx_BUSY)
	{
		/* Check for the Timeout */
    if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
    {        
			return W25Qx_TIMEOUT;
    }
	}
	
	return W25Qx_OK;
}
 
 /**********************************************************************************
  * 函数功能: 获取设备ID
  */
void BSP_W25Qx_Read_ID(uint8_t *ID)
{
	uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
	
	W25Qx_Enable();

	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 4, W25Qx_TIMEOUT_VALUE);	
	HAL_SPI_Receive(W25QX_SPI_Handler,ID, 2, W25Qx_TIMEOUT_VALUE);
	
	W25Qx_Disable();
		
}
 
 /**********************************************************************************
  * 函数功能: 读数据
  * 输入参数: 缓存数组指针、读地址、字节数
  */
uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
	uint8_t cmd[4];
 
	/* Configure the command */
	cmd[0] = READ_CMD;
	cmd[1] = (uint8_t)(ReadAddr >> 16);
	cmd[2] = (uint8_t)(ReadAddr >> 8);
	cmd[3] = (uint8_t)(ReadAddr);
	
	W25Qx_Enable();
	
	/* Send the read ID command */
	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 4, W25Qx_TIMEOUT_VALUE);	
	

	/* Reception of the data */
	if (HAL_SPI_Receive(W25QX_SPI_Handler, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)

  {
    return W25Qx_ERROR;
  }
	W25Qx_Disable();
	return W25Qx_OK;
}




 /**********************************************************************************
  * 函数功能: 写数据
  * 输入参数: 缓存数组指针、写地址、字节数
  */
uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
	uint8_t cmd[4];
	uint32_t end_addr, current_size, current_addr;
	uint32_t tickstart = HAL_GetTick();
	
	/* Calculation of the size between the write address and the end of the page */
  current_addr = 0;
 
  while (current_addr <= WriteAddr)
  {
    current_addr += W25Q128FV_PAGE_SIZE;
  }
  current_size = current_addr - WriteAddr;
 
  /* Check if the size of the data is less than the remaining place in the page */
  if (current_size > Size)
  {
    current_size = Size;
  }
 
  /* Initialize the adress variables */
  current_addr = WriteAddr;
  end_addr = WriteAddr + Size;
	
  /* Perform the write page by page */
  do
  {
		/* Configure the command */
		cmd[0] = PAGE_PROG_CMD;
		cmd[1] = (uint8_t)(current_addr >> 16);
		cmd[2] = (uint8_t)(current_addr >> 8);
		cmd[3] = (uint8_t)(current_addr);
 
		/* Enable write operations */
		BSP_W25Qx_WriteEnable();
	
		W25Qx_Enable();
		

		 /* Send the command */
    if (HAL_SPI_Transmit(W25QX_SPI_Handler,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    {
      return W25Qx_ERROR;
    }
    

		/* Transmission of the data */
		if (HAL_SPI_Transmit(W25QX_SPI_Handler, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    {
      return W25Qx_ERROR;
    }
			W25Qx_Disable();
    	/* Wait the end of Flash writing */
		while(BSP_W25Qx_GetStatus() == W25Qx_BUSY)
		{
			/* Check for the Timeout */
			if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
			{        
				return W25Qx_TIMEOUT;
			}
		}
    
    /* Update the address and size variables for next page programming */
    current_addr += current_size;
    pData += current_size;
    current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;
  } while (current_addr < end_addr);
 
	
	return W25Qx_OK;
}
 
 /**********************************************************************************
  * 函数功能: 块擦除
  * 输入参数: 地址
  */
uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)
{
	uint8_t cmd[4];
	uint32_t tickstart = HAL_GetTick();
	cmd[0] = SECTOR_ERASE_CMD;
	cmd[1] = (uint8_t)(Address >> 16);
	cmd[2] = (uint8_t)(Address >> 8);
	cmd[3] = (uint8_t)(Address);
	
	/* Enable write operations */
	BSP_W25Qx_WriteEnable();
	
	/*Select the FLASH: Chip Select low */
	W25Qx_Enable();
	

	/* Send the SECTOR_ERASE command */
	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 4, W25Qx_TIMEOUT_VALUE);	


	/*Deselect the FLASH: Chip Select high */
	W25Qx_Disable();
	
	/* Wait the end of Flash writing */
	while(BSP_W25Qx_GetStatus() == W25Qx_BUSY)
	{
		/* Check for the Timeout */
    if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)
    {        
			return W25Qx_TIMEOUT;
    }
	}
	return W25Qx_OK;
}
 
 /**********************************************************************************
  * 函数功能: 芯片擦除
  */
uint8_t BSP_W25Qx_Erase_Chip(void)
{
	uint8_t cmd[4];
	uint32_t tickstart = HAL_GetTick();
	cmd[0] = CHIP_ERASE_CMD;
	
	/* Enable write operations */
	BSP_W25Qx_WriteEnable();
	
	/*Select the FLASH: Chip Select low */
	W25Qx_Enable();
	
	/* Send the CHIP_ERASE command */
	HAL_SPI_Transmit(W25QX_SPI_Handler, cmd, 1, W25Qx_TIMEOUT_VALUE);	

	
	/*Deselect the FLASH: Chip Select high */
	W25Qx_Disable();
	
	/* Wait the end of Flash writing */
	while(BSP_W25Qx_GetStatus() != W25Qx_BUSY)
	{
		/* Check for the Timeout */
    if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)
    {        
			return W25Qx_TIMEOUT;
    }
	}
	return W25Qx_OK;
}
 

void BSP_W25QX_Test(void)
{
	uint8_t wData[0x100];   //写缓存数组
	uint8_t rData[0x100];   //读缓存数组
	uint8_t ID[4];          //设备ID缓存数组
	uint32_t i;
	
	printf("\r\n SPI-W25Qxx Example \r\n\r\n");
 
	/*-Step1- 验证设备ID  ************************************************Step1*/ 
	BSP_W25Qx_Init();
	BSP_W25Qx_Read_ID(ID);
    //第一位厂商ID固定0xEF,第二位设备ID根据容量不同,具体为:
     //W25Q16为0x14、32为0x15、40为0x12、64为0x16、80为0x13、128为0x17
	//if((ID[0] != 0xEF) | (ID[1] != 0x16)) 
	if((ID[0] != W25Q64_FLASH_ID >> 8) | (ID[1] != (W25Q64_FLASH_ID&0xFF)))
	{                                
		printf("something wrong in Step1 \r\n");
	}
	else
	{
		printf(" W25Qxx ID is : ");
		for(i=0;i<2;i++)
		{
			printf("0x%02X ",ID[i]);
		}
		printf("\r\n");
	}
	/*-Step2- 擦除块  ************************************************Step2*/ 	
	if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
		printf(" QSPI Erase Block OK!\r\n");
	else
		printf("something wrong in Step2\r\n");
	/*-Step3- 写数据  ************************************************Step3*/	
	for(i =0;i<0x100;i ++)
	{
			wData[i] = i;
            rData[i] = 0;
	}
	
	if(BSP_W25Qx_Write(wData,0x00,0x100)== W25Qx_OK)
		printf(" QSPI Write OK!\r\n");
	else
		printf("something wrong in Step3\r\n");
    /*-Step4- 读数据  ************************************************Step4*/	
	
	if(BSP_W25Qx_Read(rData,0x00,0x100)== W25Qx_OK)
		printf(" QSPI Read ok\r\n\r\n");
	else
		printf("something wrong in Step4\r\n");
	printf("QSPI Read Data : \r\n");
	for(i =0;i<0x100;i++)
		printf("0x%02X  ",rData[i]);
	printf("\r\n\r\n");
	/*-Step5- 数据对比  ************************************************Step5*/		
	if(memcmp(wData,rData,0x100) == 0 ) 
		printf(" W25Q64FV QuadSPI Test OK\r\n");
	else
		printf(" W25Q64FV QuadSPI Test False\r\n");

}

参考文章:STM32系列(HAL库)——F103C8T6通过SPI方式读写W25Q64—(Flash存储模块)_stm32f1 w25q215 hal-CSDN博客


http://www.kler.cn/a/529314.html

相关文章:

  • IM 即时通讯系统-50-[特殊字符]cim(cross IM) 适用于开发者的分布式即时通讯系统
  • 智能家居监控系统数据收集积压优化
  • jvm - GC篇
  • 前端知识速记—JS篇:null 与 undefined
  • 【回溯】目标和 字母大小全排列
  • 深度学习篇---数据存储类型
  • C++STL之stack和queue容器(详细+通俗易懂)
  • 课设:【ID0022】火车票售票管理系统(前端)
  • Qt 5.14.2 学习记录 —— 이십이 QSS
  • 【AI文章解读】《No, DeepSeek Is Not A ‘Sputnik Moment’》
  • 信息学奥赛一本通 ybt 1608:【 例 3】任务安排 3 | 洛谷 P5785 [SDOI2012] 任务安排
  • 制造业数字化转型:从标准化设备到数据与智能算法的共生革命
  • 《基于单中心损失监督的频率感知判别特征学习用于人脸伪造检测 》学习笔记
  • PostgreSQL 数据库视图基础操作
  • tf.Keras (tf-1.15)使用记录1-基础模型创建的两种方法
  • 【股票数据API接口48】如何获取股票最新分时BOLL数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
  • 【Python】理解Python中的协程和生成器:从yield到async
  • PostgreSQL 数据库备份与还原
  • 如何使用SliverList组件
  • 数据分析系列--⑨RapidMiner训练集、测试集、验证集划分
  • 拉格朗日定理
  • C++编程语言:抽象机制:模板(Bjarne Stroustrup)
  • 【网站建设:HTTPS - 如何生成免费SSL证书,并自动更新】
  • 【自开发工具介绍】SQLSERVER的ImpDp和ExpDp工具01
  • RabbitMQ持久化队列配置修改问题
  • python-leetcode-二叉搜索树迭代器