最近使用到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);
}
4303

被折叠的 条评论
为什么被折叠?



