stm32f469 Qspi+Dma驱动w25q256

        最近使用到stm32f469驱动w25q256,但硬件上只接了Qspi的clk、cs、io1、io2引脚,io3和io4接到普通io脚上,参考stm32的官方例程和网上一些例子后,测试能正常使用,在此记录一下。

W25q256.h

/* IO 定义 */
#define QSPIx_CLK_PIN                 GPIO_Pin_7
#define QSPIx_CLK_GPIO_PORT           GPIOA
#define QSPIx_CLK_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define QSPIx_CLK_SOURCE              GPIO_PinSource7
#define QSPIx_CLK_AF                  GPIO_AF10_QUADSPI

#define QSPIx_D0_PIN                  GPIO_Pin_9
#define QSPIx_D0_GPIO_PORT            GPIOC
#define QSPIx_D0_GPIO_CLK             RCC_AHB1Periph_GPIOC
#define QSPIx_D0_SOURCE               GPIO_PinSource9
#define QSPIx_D0_AF                   GPIO_AF9_QUADSPI

#define QSPIx_D1_PIN                  GPIO_Pin_10
#define QSPIx_D1_GPIO_PORT            GPIOC
#define QSPIx_D1_GPIO_CLK             RCC_AHB1Periph_GPIOC
#define QSPIx_D1_SOURCE               GPIO_PinSource10
#define QSPIx_D1_AF                   GPIO_AF9_QUADSPI

#define QSPIx_CS_PIN                  GPIO_Pin_6
#define QSPIx_CS_GPIO_PORT            GPIOB
#define QSPIx_CS_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define QSPIx_CS_SOURCE               GPIO_PinSource6
#define QSPIx_CS_AF                   GPIO_AF10_QUADSPI

#define QSPIx_D2_PIN                  GPIO_Pin_15
#define QSPIx_D2_GPIO_PORT            GPIOA
#define QSPIx_D2_GPIO_CLK             RCC_AHB1Periph_GPIOA

#define QSPIx_D3_PIN                  GPIO_Pin_8
#define QSPIx_D3_GPIO_PORT            GPIOC
#define QSPIx_D3_GPIO_CLK             RCC_AHB1Periph_GPIOC


/* DMA 定义 */
#define QSPI_DMA_CLK					RCC_AHB1Periph_DMA2
#define QSPI_DMA_CHANNEL                DMA_Channel_3
#define QSPI_DMA_STREAM                 DMA2_Stream7
#define QSPI_DMA_FLAG_TC                DMA_FLAG_TCIF7

/* W25Q256FV基本信息 */
#define QSPI_FLASH_SIZE     25                      /* Flash大小,2^25 = 32MB*/
#define QSPI_SECTOR_SIZE    (4 * 1024)              /* 扇区大小,4KB */
#define QSPI_PAGE_SIZE      256        				/* 页大小,256字节 */
#define QSPI_END_ADDR    	(1 << QSPI_FLASH_SIZE)  /* 末尾地址 */
#define QSPI_FLASH_SIZES    32*1024*1024            /* Flash大小,2^25 = 32MB*/

/* W25Q256FV相关命令 */
#define WRITE_ENABLE_CMD				0x06	//写使能
#define	READ_STATUS_REGISTER_1_CMD		0x05	//读状态寄存器1
#define READ_JEDEC_ID_CMD				0x9F	//读设备id
#define SECTOR_ERASE_CMD				0x20	//扇区擦除 4K
#define PAGE_PROGRAM_CMD				0x02	//页编程
#define FAST_READ_CMD					0x0C	//快速读取-4byte地址
#define FAST_READ_DUAL_OUTPUT_CMD		0x3C	//快速读取双输出-4byte地址
#define ENTER_4_BYTE_ADDRESS_MODE_CMD	0xB7	//使能4位地址模式

1.初始化配置

QSPI_InitTypeDef  QSPI_InitStructure;
QSPI_ComConfig_InitTypeDef  QSPI_ComConfig_InitStructure;
DMA_InitTypeDef  DMA_InitStructure;

//GPIO初始化
static void QSPI_GPIO_Config(void)
{	
  GPIO_InitTypeDef GPIO_InitStructure;
  /* 使能时钟 */ 
  RCC_AHB1PeriphClockCmd(QSPIx_CLK_GPIO_CLK|QSPIx_CS_GPIO_CLK|QSPIx_D0_GPIO_CLK|\             
                    QSPIx_D1_GPIO_CLK | QSPIx_D2_GPIO_CLK | QSPIx_D3_GPIO_CLK, ENABLE);
  //复用qspi功能
  GPIO_PinAFConfig(QSPIx_CLK_GPIO_PORT, QSPIx_CLK_SOURCE, QSPIx_CLK_AF);
  GPIO_PinAFConfig(QSPIx_CS_GPIO_PORT, QSPIx_CS_SOURCE, QSPIx_CS_AF);
  GPIO_PinAFConfig(QSPIx_D0_GPIO_PORT, QSPIx_D0_SOURCE, QSPIx_D0_AF);
  GPIO_PinAFConfig(QSPIx_D1_GPIO_PORT, QSPIx_D1_SOURCE, QSPIx_D1_AF);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  
  /* QSPI CLK pin configuration */
  GPIO_InitStructure.GPIO_Pin = QSPIx_CLK_PIN;
  GPIO_Init(QSPIx_CLK_GPIO_PORT, &GPIO_InitStructure);
  
  /* QSPI D0 pin configuration */
  GPIO_InitStructure.GPIO_Pin = QSPIx_D0_PIN;
  GPIO_Init(QSPIx_D0_GPIO_PORT, &GPIO_InitStructure);  
  
  /* QSPI D1 pin configuration */
  GPIO_InitStructure.GPIO_Pin = QSPIx_D1_PIN;
  GPIO_Init(QSPIx_D1_GPIO_PORT, &GPIO_InitStructure);  
  
  /* QSPI CS pin configuration */
  GPIO_InitStructure.GPIO_Pin = QSPIx_CS_PIN;
  GPIO_Init(QSPIx_CS_GPIO_PORT, &GPIO_InitStructure);
  
  /* 低电平有效 写保护*/
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Pin = QSPIx_D2_PIN;
  GPIO_Init(QSPIx_D2_GPIO_PORT, &GPIO_InitStructure);
  GPIO_ResetBits(QSPIx_D2_GPIO_PORT, QSPIx_D2_PIN);

  /* 低电平有效 暂停QspiFlash操作 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Pin = QSPIx_D3_PIN;
  GPIO_Init(QSPIx_D3_GPIO_PORT, &GPIO_InitStructure);
  GPIO_SetBits(QSPIx_D3_GPIO_PORT, QSPIx_D3_PIN); 
}

//Dma初始化
static void Qspi_DMA_Config(void)
{
	/* 使能时钟 */
	RCC_AHB1PeriphClockCmd(QSPI_DMA_CLK, ENABLE);	
	
	DMA_StructInit(&DMA_InitStructure);
	DMA_DeInit(QSPI_DMA_STREAM);	

//	DMA_InitStructure.DMA_BufferSize         = BUFFERSIZE;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;	
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & QUADSPI->DR ;
	DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Channel            = QSPI_DMA_CHANNEL;
	DMA_Init(QSPI_DMA_STREAM, &DMA_InitStructure);
}

//Qspi初始化
static void Qspi_Init(void)
{	
	RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_QSPI, ENABLE);
	
	/* Initialize QuadSPI ------------------------------------------------------*/
	QSPI_StructInit(&QSPI_InitStructure);
	QSPI_InitStructure.QSPI_SShift    = QSPI_SShift_HalfCycleShift; //QUADSPI在FLASH驱动信号后过半个CLK周期才对FLASH驱动的数据采样。在外部信号延迟时,这有利于推迟数据采样。
	QSPI_InitStructure.QSPI_Prescaler = 1;							//180Mhz / (QSPI_Prescaler+1) = 90Mhz
	QSPI_InitStructure.QSPI_CKMode    = QSPI_CKMode_Mode0;			//MODE0: 表示片选信号空闲期间,CLK时钟信号是低电平
	QSPI_InitStructure.QSPI_CSHTime   = QSPI_CSHTime_5Cycle;		//命令之间的CS片选至少保持x个时钟周期的高电平, 由手册9.6知/CS Deselect Time >=50, 1/90 = 11.11ns,
	QSPI_InitStructure.QSPI_FSize     = 0x18;						//W25Q256总大小为256M-Bit = 32 M-Byte  = 2 ^ 25 Byte = 2^(FlashSize + 1), 所以Flash Size取值24
	QSPI_InitStructure.QSPI_FSelect   = QSPI_FSelect_1;				//QSPI有两个BANK,这里使用的BANK1
	QSPI_InitStructure.QSPI_DFlash    = QSPI_DFlash_Disable;		//仅使用了BANK1,这里是禁止双BANK
	QSPI_Init(&QSPI_InitStructure);		
	
  /* Initialize Command Config -----------------------------------------------*/	
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize      = QSPI_ComConfig_ADSize_32bit;				//32位地址
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode       = QSPI_ComConfig_IMode_1Line;				//1线方式发送指令
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode      = QSPI_ComConfig_ABMode_NoAlternateByte;	//无交替字节
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode     = QSPI_ComConfig_DDRMode_Disable;			//不支持DDR
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC        = QSPI_ComConfig_DHHC_Disable;				
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode    = QSPI_ComConfig_SIOOMode_Disable;			//每次传输都发指令				
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);
	QSPI_Cmd(ENABLE);		
}

2.读写操作

//读取w25q256芯片ID,spi mod->0xEF4019,qsip mod->0xEF6019
uint32_t QSPI_ReadID(void)
{
	uint32_t id;
	uint8_t rxbuff[5] = {0};	

	QSPI_SetDataLength(2);	//BUFFERSIZE-1
	QSPI_DMACmd(ENABLE);
	
	//基本配置
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode 	 = QSPI_ComConfig_IMode_1Line;				//1线方式发送指令
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize 	 = QSPI_ComConfig_ADSize_32bit;				//32位地址
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode 	 = QSPI_ComConfig_ABMode_NoAlternateByte;	//无交替字节
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode  = QSPI_ComConfig_DDRMode_Disable;			//不支持DDR
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC 	 = QSPI_ComConfig_DHHC_Disable;				//不延时半个HCLK时钟周期
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable;			//每次传输都发指令
	//
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode       = QSPI_ComConfig_FMode_Indirect_Read;	//功能模式-读
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins 		= READ_JEDEC_ID_CMD;					//读取ID命令
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode		= QSPI_ComConfig_ADMode_NoAddress;		//无地址
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode 		= QSPI_ComConfig_DMode_1Line;			//1线数据
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0; 									//空周期
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure); 	
	
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rxbuff;
	DMA_InitStructure.DMA_BufferSize 	  = 3;
	DMA_InitStructure.DMA_DIR             = DMA_DIR_PeripheralToMemory;	
	DMA_InitStructure.DMA_Priority        = DMA_Priority_High;          
	DMA_Init(QSPI_DMA_STREAM, &DMA_InitStructure);
	DMA_Cmd(QSPI_DMA_STREAM, ENABLE);
	
	/* Wait for the end of Transfer */
	while(DMA_GetFlagStatus(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC) == RESET)
	{}  
	DMA_ClearFlag(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC);
	DMA_Cmd(QSPI_DMA_STREAM, DISABLE);
	QSPI_DMACmd(DISABLE);	
	
	id = (rxbuff[0] << 16) | (rxbuff[1] << 8 ) | rxbuff[2];	
		
	return id;
}

//设置4位地址模式
static void QSPI_Set4ByteAddressMode(void)
{
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure); 
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_32bit;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode  = QSPI_ComConfig_IMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode  = QSPI_ComConfig_DMode_NoData;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode  = QSPI_ComConfig_FMode_Indirect_Write;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins    = ENTER_4_BYTE_ADDRESS_MODE_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);	
	
	while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)
	{}	
}

//写使能
static void QSPI_WriteEnable(void)
{	
	//基本配置
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode 	 = QSPI_ComConfig_IMode_1Line;				//1线方式发送指令
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize   = QSPI_ComConfig_ADSize_32bit;				//32位地址
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode 	 = QSPI_ComConfig_ABMode_NoAlternateByte;	//无交替字节
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode  = QSPI_ComConfig_DDRMode_Disable;			//不支持DDR
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC	 = QSPI_ComConfig_DHHC_Disable;				//不延时半个HCLK时钟周期
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable;			//每次传输都发指令
	//写使能
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins 		= WRITE_ENABLE_CMD;						//写使能指令
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode       = QSPI_ComConfig_FMode_Indirect_Write;	//间接模式写
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode 		= QSPI_ComConfig_ADMode_NoAddress;		//无地址
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode 		= QSPI_ComConfig_DMode_NoData;			//无数据
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0; 									//空周期
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure); 
	
	/* Switch to Autopolling mode for the end of the Command */
	while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)
	{}
	QSPI_AutoPollingMode_SetInterval(0x10);
	QSPI_AutoPollingMode_Config(0x02, 0x02, QSPI_PMM_AND);
	QSPI_AutoPollingModeStopCmd(ENABLE);
	QSPI_SetDataLength(0x00);

	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode  = QSPI_ComConfig_FMode_Auto_Polling;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode  = QSPI_ComConfig_DMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins    = READ_STATUS_REGISTER_1_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure); 

	while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET)
	{}
	QSPI_ClearFlag(QSPI_FLAG_SM);
	QSPI_ClearFlag(QSPI_FLAG_TC);
	while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)
	{}
}

//等待QSPI Flash就绪,主要用于Flash擦除和页编程时使用
static void QSPI_AutoPollingMemReady(void)
{
	/* Wait for end of Cmd */
	while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)
	{}
	QSPI_SetDataLength(0x00);
	QSPI_AutoPollingMode_Config(0x00, 0x01, QSPI_PMM_AND);
	QSPI_AutoPollingModeStopCmd(ENABLE);
	QSPI_SetDataLength(0);

	/* Reconfigure QSPI to automatic polling mode to wait for end of Command*/
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode  = QSPI_ComConfig_FMode_Auto_Polling;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode  = QSPI_ComConfig_DMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins    = READ_STATUS_REGISTER_1_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure); 

	while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET)
	{}

	QSPI_ClearFlag(QSPI_FLAG_SM);
	QSPI_ClearFlag(QSPI_FLAG_TC);
}

/*	擦除指定的扇区,扇区大小4KB
 address:扇区地址,以4KB为单位的地址
*/
void QSPI_SectorErase(uint32_t address)
{
	QSPI_WriteEnable();	
	
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure); 
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_32bit;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode  = QSPI_ComConfig_IMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode  = QSPI_ComConfig_DMode_NoData;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode  = QSPI_ComConfig_FMode_Indirect_Write;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins    = SECTOR_ERASE_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);	
	
	/* 设置扇区地址擦除 */
	QSPI_SetAddress(address);  

	while (QSPI_GetFlagStatus(QSPI_FLAG_TC) == RESET)
	{}	
		
	QSPI_AutoPollingMemReady();	
}

/*	页编程,页大小256字节
 address:目标区域首地址,以也为单位256byte
 txBuff :数据缓冲区首地址
 len	:写入数据的长度,不大于256
*/
void QSPI_PageProgram(uint32_t address, uint8_t txBuff[], uint32_t len)
{
	QSPI_WriteEnable();
	QSPI_DMACmd(ENABLE);	
	
	QSPI_SetDataLength(len-1);
   
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure); 
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode       = QSPI_ComConfig_IMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode      = QSPI_ComConfig_ADMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode       = QSPI_ComConfig_DMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode       = QSPI_ComConfig_FMode_Indirect_Write;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize      = QSPI_ComConfig_ADSize_32bit; 
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins         = PAGE_PROGRAM_CMD;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure); 
	QSPI_SetAddress(address);	
	
	DMA_InitStructure.DMA_BufferSize      = len;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)txBuff;
	DMA_InitStructure.DMA_DIR             = DMA_DIR_MemoryToPeripheral;	
	DMA_InitStructure.DMA_Priority        = DMA_Priority_Low;          
	DMA_Init(QSPI_DMA_STREAM, &DMA_InitStructure);
	DMA_Cmd(QSPI_DMA_STREAM, ENABLE);	
	
	/* Wait for the end of Transfer */
	while(DMA_GetFlagStatus(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC) == RESET)
	{}  
	DMA_ClearFlag(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC);
	DMA_Cmd(QSPI_DMA_STREAM, DISABLE);
	QSPI_DMACmd(DISABLE);	
		
	QSPI_AutoPollingMemReady();	
}

/*	快速读取flash数据
 address:目标区域首地址
 rxBuff :数据缓冲区首地址
 len	:读取数据的长度
*/
void QSPI_FastRead(uint32_t address, uint8_t rxBuff[], uint32_t len)
{
	QSPI_SetDataLength(len-1);
	QSPI_DMACmd(ENABLE);
	
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize      = QSPI_ComConfig_ADSize_32bit;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode       = QSPI_ComConfig_IMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode      = QSPI_ComConfig_ADMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode       = QSPI_ComConfig_DMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode       = QSPI_ComConfig_FMode_Indirect_Read;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0x08;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins         = FAST_READ_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);
	QSPI_SetAddress(address);

	DMA_InitStructure.DMA_BufferSize      = len;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rxBuff;
	DMA_InitStructure.DMA_DIR             = DMA_DIR_PeripheralToMemory;	
	DMA_InitStructure.DMA_Priority        = DMA_Priority_High;          
	DMA_Init(QSPI_DMA_STREAM, &DMA_InitStructure);
	DMA_Cmd(QSPI_DMA_STREAM, ENABLE);		

	/* Wait for the end of Transfer */
	while(DMA_GetFlagStatus(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC) == RESET)
	{}  
	DMA_ClearFlag(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC);      
	DMA_Cmd(QSPI_DMA_STREAM, DISABLE);     
	QSPI_DMACmd(DISABLE);		 		  
}

/*	快速读取flash数据--双输出
 address:目标区域首地址
 rxBuff :数据缓冲区首地址
 len	:读取数据的长度
*/
void QSPI_FastReadDualOutput(uint32_t address, uint8_t rxBuff[], uint32_t len)
{
	QSPI_SetDataLength(len-1);
	QSPI_DMACmd(ENABLE);
	
	QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize      = QSPI_ComConfig_ADSize_32bit;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode       = QSPI_ComConfig_IMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode      = QSPI_ComConfig_ADMode_1Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode       = QSPI_ComConfig_DMode_2Line;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode       = QSPI_ComConfig_FMode_Indirect_Read;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0x08;
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins         = FAST_READ_DUAL_OUTPUT_CMD;
	QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);
	QSPI_SetAddress(address);

	DMA_InitStructure.DMA_BufferSize      = len;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rxBuff;
	DMA_InitStructure.DMA_DIR             = DMA_DIR_PeripheralToMemory;	
	DMA_InitStructure.DMA_Priority        = DMA_Priority_High;          
	DMA_Init(QSPI_DMA_STREAM, &DMA_InitStructure);
	DMA_Cmd(QSPI_DMA_STREAM, ENABLE);		

	/* Wait for the end of Transfer */
	while(DMA_GetFlagStatus(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC) == RESET)
	{}  
	DMA_ClearFlag(QSPI_DMA_STREAM, QSPI_DMA_FLAG_TC);      
	DMA_Cmd(QSPI_DMA_STREAM, DISABLE);     
	QSPI_DMACmd(DISABLE);		 		  
}

 3.测试

uint8_t aTxBuffer[100] = "QSPI Interrupt Read Write Example: QSPI -> QSPI Flash using DMA";
uint8_t aRxBuffer[100];
uint32_t flashID;

void W25Q256_Init(void)
{
	QSPI_GPIO_Config();
	Qspi_DMA_Config();
	Qspi_Init();
	QSPI_Set4ByteAddressMode();//因为w25q256是32m,24位地址不够用,要设置32位地址
	
	flashID = QSPI_ReadID();//读取w25q256 ID
}


void W25Q256_Test(void)
{	
	QSPI_SectorErase(0x1FFF000);
	QSPI_PageProgram(0x1FFF100, aTxBuffer, 50);
//	QSPI_FastRead(0x1FFF000, aRxBuffer, 100);
	QSPI_FastReadDualOutput(0x1FFF100, aRxBuffer, 100);	
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值