IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> H750下W25QXX下载算法(stlder)制作(1) -> 正文阅读

[嵌入式]H750下W25QXX下载算法(stlder)制作(1)

代码地址

夕阳武士/H750_W25QXXhttps://gitee.com/wangchief/H750_W25QXX

1、为什么要制作stlder算法

????????我们使用的是正点原子的H750核心板进行开发,H750的内部flash只有128k,无法满足比较大型程序的开发。H750提供了QSPI接口,我们可以通过QSPI接口访问外部的FLASH来扩展芯片的FLASH内容。在程序下载及调试过程中需要使用到stldr算法的实现。

2、实现步骤

  1. 实现在128kb内部flash基础上进行QSPI接口访问FLASH的程序开发和验证。
  2. 打包制作stlder算法,实现对外部flash的访问。
  3. 实现整体程序在外部flash的运行
  4. 通过bootloader来实现程序的跳转。

3、本章内容

????????本章节实现上述不走 ,验证128k内部flash内QSPI接口对外部W25QXX的访问。

3.1开发硬件环境

  • ? ? ? ? 正点原子H750核心板
  • ? ? ? ? 正点原子北极星底板

3.2软件开发环境

  • STM32CubeIDE 1.90
  • STM32CubeMX 6.5
  • STM32Cube_FW_H7 V1.10.0

3.2工程创建

3.3?Cubemx配置

?

?3.4?驱动开发

? ? ? ? 设计编写bsp_w25qxx.c和bsp_w25qxx.h两个文件实现对W25QXX系列QSPI访问的支持,目前手头只有W25Q64芯片,后续驱动对其他型号进行支持完善。

? ? ? ? 对外接口

函数? ? ? ? ? ? ??说明
bsp_w25qxx_Init初始化w25qxx
bsp_w25qxx_Read读取w25qxx
bsp_w25qxx_EraseSector擦除w25qxx的一个扇区(4k)
bsp_w25qxx_EraseBlock擦除w25qxx的一个块(64k)
bsp_w25qxx_EraseChip擦除整片w25qxx
bsp_w25qxx_Write写入w25qxx
bsp_w25qxx_MemoryMapedEnter进入内存映射模式

?内部接口

函数?说明
bsp_w25qxx_AutoPollingNotBusy阻塞方式等待W25QXX不繁忙
bsp_w25qxx_AutoPollingWriteEnable阻塞方式等待W25QXX写使能
bsp_w25qxx_Reset软件复位W25QXX
bsp_w25qxx_GetID获取芯片的ID
bsp_w25qxx_GetUID获取芯片的UID
bsp_w25qxx_WriteEnable写使能
EndianSwap大小端转换
bsp_w25qxx_WriteStatusReg写单个状态寄存器
bsp_w25qxx_ReadStatusReg读取单个状态寄存器
bsp_w25qxx_GetStatusRegs获取3个状态寄存器
#ifndef __BSP_W25QXX_H__
#define __BSP_W25QXX_H__
/***********************************************************************************
  									全局变量
***********************************************************************************/
#include "main.h"
/***********************************************************************************
  									命令宏定义
***********************************************************************************/
#define CMD_ENABLE_RESET	0x66
#define CMD_RESET			0x99


#define	CMD_GET_ID			0x9F
#define CMD_GET_UID			0x4B

#define CMD_WRITE_ENABLE	0x06

#define CMD_READ			0xEB
#define CMD_WRITE			0x32
#define CMD_ERASE_SECTOR	0x20
#define CMD_ERASE_BLOCK		0xD8
#define CMD_ERASE_CHIP		0xC7

#define CMD_GET_REG1		0x05
#define CMD_GET_REG2		0x35
#define CMD_GET_REG3		0x15

#define CMD_SET_REG1		0x01
#define CMD_SET_REG2		0x31
#define CMD_SET_REG3		0x11
/***********************************************************************************
  									函数声明
***********************************************************************************/
extern uint8_t bsp_w25qxx_Init();
extern uint8_t bsp_w25qxx_Read(uint32_t addr , uint8_t*buff , uint32_t len);
extern uint8_t bsp_w25qxx_EraseSector(uint32_t addr);
extern uint8_t bsp_w25qxx_EraseBlock(uint32_t addr);
extern uint8_t bsp_w25qxx_EraseChip();
extern uint8_t bsp_w25qxx_Write(uint32_t addr , uint8_t*buff , uint32_t len);
extern uint8_t bsp_w25qxx_MemoryMapedEnter();
#endif
/***********************************************************************************
  									头文件
***********************************************************************************/
#include "bsp_w25qxx.h"
#include "string.h"
/***********************************************************************************
  									宏定义
***********************************************************************************/
#define DEBUG_ENABLE
/***********************************************************************************
  									全局变量
***********************************************************************************/
extern QSPI_HandleTypeDef hqspi;

uint32_t 	ChipID;
uint64_t 	ChipUID;
uint8_t		StatusReg[3] ={0};
/***********************************************************************************
  									函数声明
***********************************************************************************/
static uint8_t 	bsp_w25qxx_AutoPollingNotBusy();
static uint8_t 	bsp_w25qxx_AutoPollingWriteEnable();
static uint8_t 	bsp_w25qxx_Reset();
static uint8_t 	bsp_w25qxx_GetID();
static uint8_t 	bsp_w25qxx_GetUID();
static uint8_t 	bsp_w25qxx_WriteEnable();
static void 	EndianSwap(uint8_t* pdata , uint8_t len);
static uint8_t 	bsp_w25qxx_WriteStatusReg(uint8_t regindex , uint8_t data);
static uint8_t 	bsp_w25qxx_ReadStatusReg(uint8_t regindex , uint8_t* data);
static int8_t   bsp_w25qxx_GetStatusRegs();
/***********************************************************************************
  									全局函数
***********************************************************************************/
/**
***************************************************
* @brief    bsp_w25qxx_Init
* @note     初始化w25qxx芯片
* 			进行芯片复位,ID读取,UID读取
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_Init()
{
	//复位芯片
	if(bsp_w25qxx_Reset() != 0)
		return 1;

	//获取芯片ID信息
	if(bsp_w25qxx_GetID() != 0)
		return 1;

	//获取芯片UID信息
	if(bsp_w25qxx_GetUID() != 0)
		return 1;

	//使能QSPI模式  STATUS REG2 的QE写为1
	if(bsp_w25qxx_WriteStatusReg(2 , 0x02) != 0)
		return 1;

	//DRV 100%    WPS = 0
	if(bsp_w25qxx_WriteStatusReg(3 , 0) != 0)
		return 1;

	//获取状态寄存器
	if(bsp_w25qxx_GetStatusRegs() != 0)
		return 1;
	return 0;
}

/**
***************************************************
* @brief    bsp_w25qxx_Read
* @note     读取芯片数据
* @para
* 			addr		读取地址
* 			buff		存放缓冲
* 			len			读取长度
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_Read(uint32_t addr , uint8_t*buff , uint32_t len)
{
    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*24位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    command.Instruction 			= CMD_READ;   						/*读取数据*/
    command.DummyCycles 			= 6;                                /*6个空周期*/
    command.AddressMode 			= QSPI_ADDRESS_4_LINES;             /*4地址信息*/
    command.DataMode 				= QSPI_DATA_4_LINES;                /*4线数据*/
    command.NbData 					= len;                             	/*读取数据大小 */
    command.Address 				= addr;                            	/*读取地址 */

    /* 发送读取命令 */
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	/* 等待读取完成 */
	if (HAL_QSPI_Receive(&hqspi, buff, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	return 0;
}
/**
***************************************************
* @brief    bsp_w25qxx_EraseSector
* @note     擦除4k数据
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_EraseSector(uint32_t addr)
{
    QSPI_CommandTypeDef command = {0};

    //WEL使能
    if(bsp_w25qxx_WriteEnable() != 0)
    	return 1;

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*24位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    command.Instruction 			= CMD_ERASE_SECTOR;   				/*擦除sector 4k*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_1_LINE;              /*1地址信息*/
    command.DataMode 				= QSPI_DATA_NONE;                	/*0线数据*/
    command.NbData 					= 0;                             	/*数据*/
    command.Address 				= addr;                            	/*地址 */

    //发送命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;

	//等待不繁忙,即操作完成
	return bsp_w25qxx_AutoPollingNotBusy();
}

/**
***************************************************
* @brief    bsp_w25qxx_EraseBlock
* @note     擦除64k数据
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_EraseBlock(uint32_t addr)
{
    QSPI_CommandTypeDef command = {0};

    //WEL使能
    if(bsp_w25qxx_WriteEnable() != 0)
    	return 1;


    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*24位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */


    command.Instruction 			= CMD_ERASE_BLOCK;   				/*擦除block 64k*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_1_LINE;              /*1地址信息*/
    command.DataMode 				= QSPI_DATA_NONE;                	/*0线数据*/
    command.NbData 					= 0;                             	/*数据*/
    command.Address 				= addr;                            	/*地址 */

    //发送命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;

    //等待不繁忙,即操作完成
	return bsp_w25qxx_AutoPollingNotBusy();
}
/**
***************************************************
* @brief    bsp_w25qxx_EraseChip
* @note     正片擦除
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_EraseChip()
{
    QSPI_CommandTypeDef command = {0};

    //WEL使能
    if(bsp_w25qxx_WriteEnable() != 0)
    	return 1;

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*24位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */


    command.Instruction 			= CMD_ERASE_CHIP;   				/*擦除chip*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;                /*无地址信息*/
    command.DataMode 				= QSPI_DATA_NONE;                	/*0线数据*/
    command.NbData 					= 0;                             	/*数据*/

    //发送命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;

    //等待不繁忙,即操作完成
	return bsp_w25qxx_AutoPollingNotBusy();
}
/**
***************************************************
* @brief    bsp_w25qxx_Write
* @note     写入芯片数据,最大写入1页256个数据,大于256,从头写
* @para
* 			addr		写入地址
* 			buff		写入数据缓冲区
* 			len			写入长度
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_Write(uint32_t addr , uint8_t*buff , uint32_t len)
{
    QSPI_CommandTypeDef command = {0};

    //WEL使能
    if(bsp_w25qxx_WriteEnable() != 0)
    	return 1;

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*24位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_ONLY_FIRST_CMD;    /*只发送一次*/


    command.Instruction 			= CMD_WRITE;   						/*写入数据*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_1_LINE;              /*1地址信息*/
    command.DataMode 				= QSPI_DATA_4_LINES;                /*4线数据*/
    command.NbData 					= len;                             	/*数据*/
    command.Address 				= addr;                            	/*地址 */

    //发送写命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//写数据
	if (HAL_QSPI_Transmit(&hqspi, buff, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	return bsp_w25qxx_AutoPollingNotBusy();
}
/**
***************************************************
* @brief    bsp_w25qxx_MemoryMapedEnter
* @note     QSPI进入内存映射模式,地址为0x90000000
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
uint8_t bsp_w25qxx_MemoryMapedEnter()
{
	QSPI_CommandTypeDef 		command = {0};
	QSPI_MemoryMappedTypeDef 	mappedcfg = {0};

	command.InstructionMode 	= QSPI_INSTRUCTION_1_LINE;      	/* 1线方式发送指令 */
	command.AddressSize 		= QSPI_ADDRESS_24_BITS;             /* 32位地址 */
	command.AlternateByteMode 	= QSPI_ALTERNATE_BYTES_NONE;  		/* 无交替字节 */
	command.DdrMode 			= QSPI_DDR_MODE_DISABLE;            /* W25Q256JV不支持DDR */
	command.DdrHoldHalfCycle 	= QSPI_DDR_HHC_ANALOG_DELAY;   		/* DDR模式,数据输出延迟 */
	command.SIOOMode 			= QSPI_SIOO_INST_EVERY_CMD;         /* 每次传输都发指令 */

	command.Instruction 		= CMD_READ; 						/* 快速读取命令 */
	command.AddressMode 		= QSPI_ADDRESS_4_LINES;             /* 4个地址线 */
	command.DataMode 			= QSPI_DATA_4_LINES;                /* 4个数据线 */
	command.DummyCycles 		= 6;                                /* 空周期 */

	/* 关闭溢出计数 */
	mappedcfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
	mappedcfg.TimeOutPeriod = 0;
	if (HAL_QSPI_MemoryMapped(&hqspi, &command, &mappedcfg) != HAL_OK)
		return 1;
	return 0;
}
/***********************************************************************************
  									局部函数
***********************************************************************************/
/**
***************************************************
* @brief    EndianSwap
* @note     数据大小端转换
* @para
* 			padat	指向待转换的数据
* 			len		数据为几字节
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static void EndianSwap(uint8_t* pdata , uint8_t len)
{
	uint8_t temp = 0;

	for(uint8_t i=0;i<len/2;i++)
	{
		temp = pdata[i];
		pdata[i] = pdata[len-i-1];
		pdata[len-i-1] = temp;
	}
}

/**
***************************************************
* @brief    bsp_w25qxx_AutoPollingNotBusy
* @note     等待BUSY信号
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t bsp_w25qxx_AutoPollingNotBusy()
{
    QSPI_CommandTypeDef 		command = {0};
    QSPI_AutoPollingTypeDef 	config = {0};

    command.InstructionMode 	= QSPI_INSTRUCTION_1_LINE;           /* 1线方式发送指令 */
    command.AddressSize 		= QSPI_ADDRESS_24_BITS;              /* 32位地址 */
    command.AlternateByteMode 	= QSPI_ALTERNATE_BYTES_NONE;         /* 无交替字节 */
    command.DdrMode 			= QSPI_DDR_MODE_DISABLE;             /* W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 	= QSPI_DDR_HHC_ANALOG_DELAY;         /* DDR模式,数据输出延迟 */
    command.SIOOMode 			= QSPI_SIOO_INST_EVERY_CMD;          /* 每次传输都发指令 */

    command.Instruction 		= CMD_GET_REG1;                      /* 读取状态命令 */
    command.AddressMode 		= QSPI_ADDRESS_NONE;                 /* 无需地址 */
    command.DataMode 			= QSPI_DATA_1_LINE;                  /* 1线数据 */
    command.DummyCycles 		= 0;                                 /* 无需空周期 */

    /* 屏蔽位设置的bit0,匹配位等待bit0为0,即不断查询状态寄存器bit0,等待其为0 */
    config.Match 			= 0x00;
    config.Mask 			= 0x01;
    config.Interval 		= 0x10;
    config.StatusBytesSize 	= 1;
    config.MatchMode 		= QSPI_MATCH_MODE_AND;
    config.AutomaticStop 	= QSPI_AUTOMATIC_STOP_ENABLE;

    if (HAL_QSPI_AutoPolling(&hqspi, &command, &config, HAL_MAX_DELAY) != HAL_OK)
		return 1;
    return 0;
}
/**
***************************************************
* @brief    bsp_w25qxx_AutoPollingWriteEnable
* @note     等待WEL信号
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t bsp_w25qxx_AutoPollingWriteEnable()
{
    QSPI_CommandTypeDef 		command = {0};
    QSPI_AutoPollingTypeDef 	config = {0};

    command.InstructionMode 	= QSPI_INSTRUCTION_1_LINE;           /* 1线方式发送指令 */
    command.AddressSize 		= QSPI_ADDRESS_24_BITS;              /* 32位地址 */
    command.AlternateByteMode 	= QSPI_ALTERNATE_BYTES_NONE;         /* 无交替字节 */
    command.DdrMode 			= QSPI_DDR_MODE_DISABLE;             /* W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 	= QSPI_DDR_HHC_ANALOG_DELAY;         /* DDR模式,数据输出延迟 */
    command.SIOOMode 			= QSPI_SIOO_INST_EVERY_CMD;          /* 每次传输都发指令 */

    command.Instruction 		= CMD_GET_REG1;                      /* 读取状态命令 */
    command.AddressMode 		= QSPI_ADDRESS_NONE;                 /* 无需地址 */
    command.DataMode 			= QSPI_DATA_1_LINE;                  /* 1线数据 */
    command.DummyCycles 		= 0;                                 /* 无需空周期 */

    /* 屏蔽位设置的bit0,匹配位等待bit0为0,即不断查询状态寄存器bit0,等待其为0 */
    config.Mask 			= 0xFD;
    config.Match 			= 0x01;
    config.MatchMode 		= QSPI_MATCH_MODE_OR;
    config.StatusBytesSize 	= 1;
    config.Interval 		= 0x10;
    config.AutomaticStop 	= QSPI_AUTOMATIC_STOP_ENABLE;

    if (HAL_QSPI_AutoPolling(&hqspi, &command, &config, HAL_MAX_DELAY) != HAL_OK)
		return 1;
    return 0;
}

/**
***************************************************
* @brief    bsp_w25qxx_Reset
* @note     复位芯片,66和99命令必须连续发送,发送完毕后至少需要等待30us
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t bsp_w25qxx_Reset()
{
    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    command.Instruction 			= CMD_ENABLE_RESET;   				/*使能重启*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_NONE;                   /*无数据信息*/
    command.NbData 					= 0;                             	/*写数据大小 */
    command.Address 				= 0;                            	/*写入地址 */

    /*复位使能*/
    if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;

	/*复位*/
    command.Instruction 			= CMD_RESET;
    if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
    return 0;
}

/**
***************************************************
* @brief    bsp_w25qxx_GetID
* @note     获取芯片的ID信息,识别芯片类型
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t bsp_w25qxx_GetID()
{
    QSPI_CommandTypeDef command = {0};


    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */


    command.Instruction 			= CMD_GET_ID;   					/*获取芯片ID*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_1_LINE;                   /*无数据信息*/
    command.NbData 					= 3;                             	/*写数据大小 */
    command.Address 				= 0;                            	/*写入地址 */

    //发送获取ID命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//获取ID
	if (HAL_QSPI_Receive(&hqspi, (uint8_t *)&ChipID, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//进行大小端转换
	EndianSwap((uint8_t *)&ChipID , 3);
	return 0;
}
/**
***************************************************
* @brief    bsp_w25qxx_GetUID
* @note     识别芯片的UID编码
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t bsp_w25qxx_GetUID()
{
    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    command.Instruction 			= CMD_GET_UID;   					/*获取芯片UID*/
    command.DummyCycles 			= 4;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_1_LINE;                 /*无数据信息*/
    command.NbData 					= 8;                             	/*写数据大小 */
    command.Address 				= 0;                            	/*写入地址 */

    //发送命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
    //接收UID信息
	if (HAL_QSPI_Receive(&hqspi, (uint8_t *)&ChipUID, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//大小端抓换
	EndianSwap((uint8_t *)&ChipUID , 8);
	return 0;
}
/**
***************************************************
* @brief    bsp_w25qxx_WriteEnable
* @note     使能W25QXX的写功能,使能状态寄存器的WEL位
* @para     NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t 	bsp_w25qxx_WriteEnable()
{
    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    command.Instruction 			= CMD_WRITE_ENABLE;   				/*写使能*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_NONE;                   /*无数据信息*/
    command.NbData 					= 0;                             	/*写数据大小 */
    command.Address 				= 0;                            	/*写入地址 */

	//发送命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//等待WEL位置位
	return bsp_w25qxx_AutoPollingWriteEnable();
}

/**
***************************************************
* @brief    bsp_w25qxx_WriteStatusReg
* @note     使能W25QXX的QSPI模式
* @para
			regindex	写第几个
			data		写入内容
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t 	bsp_w25qxx_WriteStatusReg(uint8_t regindex , uint8_t data)
{
    //使能WEL
	if(bsp_w25qxx_WriteEnable() != 0)
		return 1;

    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    /* 写序列配置 */
    if(regindex == 1)
        command.Instruction 		= CMD_SET_REG1;   					/*写status reg1*/
    else if(regindex == 2)
        command.Instruction 		= CMD_SET_REG2;   					/*写status reg2*/
    else if(regindex == 3)
        command.Instruction 		= CMD_SET_REG3;   					/*写status reg3*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_1_LINE;                 /*无数据信息*/
    command.NbData 					= 1;                             	/*写数据大小 */
    command.Address 				= 0;                            	/*写入地址 */

    //发送配置命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//发送配置信息
	if(HAL_QSPI_Transmit(&hqspi, &data, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//等待notbusy
	return bsp_w25qxx_AutoPollingNotBusy();
}
/**
***************************************************
* @brief    bsp_w25qxx_ReadStatusReg
* @note     读取status寄存器
* @para
* 			regindex	读第几个
* 			data		存放读取到的数据
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static uint8_t 	bsp_w25qxx_ReadStatusReg(uint8_t regindex , uint8_t* data)
{
    QSPI_CommandTypeDef command = {0};

    command.InstructionMode 		= QSPI_INSTRUCTION_1_LINE;          /*1线方式发送指令 */
    command.AddressSize 			= QSPI_ADDRESS_24_BITS;             /*32位地址 */
    command.AlternateByteMode 		= QSPI_ALTERNATE_BYTES_NONE;     	/*无交替字节 */
    command.DdrMode 				= QSPI_DDR_MODE_DISABLE;            /*W25Q256JV不支持DDR */
    command.DdrHoldHalfCycle 		= QSPI_DDR_HHC_ANALOG_DELAY;      	/*DDR模式,数据输出延迟 */
    command.SIOOMode 				= QSPI_SIOO_INST_EVERY_CMD;    		/*每次发送命令 */

    if(regindex == 1)
        command.Instruction 		= CMD_GET_REG1;   					/*写status reg1*/
    else if(regindex == 2)
        command.Instruction 		= CMD_GET_REG2;   					/*写status reg2*/
    else if(regindex == 3)
        command.Instruction 		= CMD_GET_REG3;   					/*写status reg3*/
    command.DummyCycles 			= 0;                                /*不需要空周期*/
    command.AddressMode 			= QSPI_ADDRESS_NONE;              	/*无地址信息*/
    command.DataMode 				= QSPI_DATA_1_LINE;                 /*无数据信息*/
    command.NbData 					= 1;                             	/*数据大小 */
    command.Address 				= 0;                            	/*入地址 */

    //发送读取命令
	if (HAL_QSPI_Command(&hqspi, &command, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	//接收数据
	if(HAL_QSPI_Receive(&hqspi, data, HAL_MAX_DELAY) != HAL_OK)
		return 1;
	return 0;
}
/**
***************************************************
* @brief    bsp_w25qxx_GetStatusRegs
* @note     获取三个status register 数据
* @para		NONE
* @retval
			0:成功
			1:失败
* @data     2022.04.28
* @auth     WXL
***************************************************
**/
static int8_t bsp_w25qxx_GetStatusRegs()
{
    if(bsp_w25qxx_ReadStatusReg(1 , &StatusReg[0]) != 0)
    	return 1;
    if(bsp_w25qxx_ReadStatusReg(2 , &StatusReg[1]) != 0)
    	return 1;
    if(bsp_w25qxx_ReadStatusReg(3 , &StatusReg[2]) != 0)
    	return 1;
    return 0;
}
#ifdef DEBUG_ENABLE
void bsp_w25qxx_test()
{

	#define SIZE 		100
	#define	ADDRESS		0
	uint8_t buff[SIZE];
	uint16_t index = 0;

	//初始化驱动。
	if(bsp_w25qxx_Init()!=0)
	{
		printf("Init w25qxx failed\r\n");
	}
	printf("Init w25qxx success\r\n");
	printf("Chip ID is %06x\r\n",ChipID);
	printf("Chip UID is %llx\r\n",ChipUID);
	printf("Status   REG1:%02x  REG2:%02x  REG3:%02x  \r\n",StatusReg[0],StatusReg[1],StatusReg[2]);




	//测试sector的擦除功能。
	printf("\r\nErase sector test\r\n");
	bsp_w25qxx_EraseSector(ADDRESS);
	printf("Read data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}
	printf("\r\nWrite data to chip\r\n");
	bsp_w25qxx_Write(ADDRESS , buff , SIZE);
	memset(buff , 0 , SIZE);
	printf("Get data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}

	//测试block的擦除功能。
	printf("\r\n\r\nErase block test \r\n");
	bsp_w25qxx_EraseBlock(ADDRESS);
	printf("Read data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}
	printf("\r\nWrite data to chip\r\n");
	bsp_w25qxx_Write(ADDRESS , buff , SIZE);
	memset(buff , 0 , SIZE);
	printf("Get data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}


	//测试chip的擦除功能。
	printf("\r\n\r\nErase chip \r\n");
	bsp_w25qxx_EraseChip();
	printf("Read data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}
	printf("\r\nWrite data to chip\r\n");
	bsp_w25qxx_Write(ADDRESS , buff , SIZE);
	memset(buff , 0 , SIZE);
	printf("Get data from chip\r\n");
	bsp_w25qxx_Read(ADDRESS , buff , SIZE);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",buff[index]);
		buff[index] = index % SIZE;
	}


	//进入mapped模式。
	printf("\r\n\r\nMaped mode entered\r\n");
	bsp_w25qxx_MemoryMapedEnter();
	uint32_t add = 0x90000000;
	printf("Read data from %x address\r\n",add+ADDRESS);
	for(index = 0;index <SIZE;index++)
	{
		if((index %15 == 0) && (index!=0))
		{
			printf("\r\n");
		}
		printf("  %02x  ",*((uint8_t*)(add+ADDRESS + index)));
	}
}
#endif




  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-02 13:29:24  更:2022-05-02 13:29:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:56:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码