STM32标准库QSPI驱动详解

张开发
2026/4/16 2:11:13 15 分钟阅读

分享文章

STM32标准库QSPI驱动详解
STM32标准库Standard Peripheral LibrarySPL作为早期固件库为QSPI外设提供了寄存器级抽象其驱动架构与HAL库存在显著差异。标准库通过stm32fxxx_qspi.c/h文件提供QSPI控制函数开发者需直接配置QUADSPI_TypeDef结构体中的寄存器而非使用HAL库的句柄机制。一、标准库QSPI驱动核心架构标准库采用分层驱动模型其核心组件包括驱动层功能模块关键函数/宏硬件抽象层寄存器映射QUADSPI-CR,QUADSPI-CCR配置层时钟/引脚初始化RCC_AHB3PeriphClockCmd(),GPIO_Init()命令层指令发送控制QSPI_SendCommand(),QSPI_ReceiveData()状态层标志位管理QSPI_GetFlagStatus(),QSPI_ClearFlag()标准库的QSPI初始化需手动配置所有时序参数以下为典型配置流程// 1. 时钟使能 RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_QSPI, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 2. GPIO配置以PB2/6/10/11/12为例 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin GPIO_Pin_2 | GPIO_Pin_6 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd GPIO_PuPd_UP; GPIO_Init(GPIOB, GPIO_InitStruct); // 3. 复用功能映射 GPIO_PinAFConfig(GPIOB, GPIO_PinSource2, GPIO_AF_QSPI); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_QSPI); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_QSPI); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_QSPI); GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_QSPI); // 4. QSPI控制器初始化 QSPI_InitTypeDef QSPI_InitStruct; QSPI_StructInit(QSPI_InitStruct); QSPI_InitStruct.QSPI_SShift QSPI_SShift_HalfCycle; // 采样移位 QSPI_InitStruct.QSPI_Prescaler 2; // 时钟分频 QSPI_InitStruct.QSPI_CKMode QSPI_CKMode_Mode0; // 时钟模式 QSPI_InitStruct.QSPI_CSHTime QSPI_CSHTime_1Cycle; // CS保持时间 QSPI_InitStruct.QSPI_FSize 23; // 闪存容量2^24 16MB QSPI_InitStruct.QSPI_FSelect QSPI_FSelect_1; // 闪存选择 QSPI_Init(QSPI_InitStruct);二、标准库命令发送机制标准库通过直接配置QUADSPI_CCR寄存器实现命令发送与HAL库的QSPI_CommandTypeDef结构体形成对比// 标准库命令发送函数示例 uint8_t QSPI_SendCommand_STD(uint32_t instruction, uint32_t address, uint32_t dummyCycles, uint32_t dataSize) { // 等待总线空闲 while(QSPI_GetFlagStatus(QUADSPI_FLAG_BUSY) SET); // 清除所有标志位 QSPI_ClearFlag(QUADSPI_FLAG_TC | QUADSPI_FLAG_TE | QUADSPI_FLAG_SM); // 配置CCR寄存器核心差异点 QUADSPI-CCR (instruction QUADSPI_CCR_INSTRUCTION_Pos) | (QSPI_CCR_IMODE_1_LINE QUADSPI_CCR_IMODE_Pos) | (QSPI_CCR_ADMODE_1_LINE QUADSPI_CCR_ADMODE_Pos) | (address QUADSPI_CCR_ADDRESS_Pos) | (dummyCycles QUADSPI_CCR_DCYC_Pos) | (QSPI_CCR_DMODE_1_LINE QUADSPI_CCR_DMODE_Pos) | (QSPI_CCR_ADSIZE_24_BITS QUADSPI_CCR_ADSIZE_Pos) | (QSPI_CCR_FMODE_INDIRECT_WRITE QUADSPI_CCR_FMODE_Pos); // 等待传输完成 while(QSPI_GetFlagStatus(QUADSPI_FLAG_TC) RESET); return QSPI_GetFlagStatus(QUADSPI_FLAG_TE) RESET ? SUCCESS : ERROR; }三、标准库与HAL库驱动对比分析特性维度标准库SPLHAL库抽象层级寄存器级封装直接操作QUADSPI-CCR高级句柄抽象使用hqspi结构体初始化复杂度需手动配置时钟、GPIO、复用功能通过MX_QSPI_Init()自动生成命令配置直接位操作寄存器使用QSPI_CommandTypeDef结构体中断处理手动配置NVIC查询标志位回调函数机制HAL_QSPI_TxCpltCallback()DMA支持需手动配置DMA通道集成DMA传输函数HAL_QSPI_Transmit_DMA()内存映射模式直接配置QUADSPI_CR的MM位专用函数HAL_QSPI_MemoryMapped()代码可移植性较低依赖具体型号较高跨系列兼容四、标准库驱动NOR Flash的典型场景以GD25Q64的Quad I/O Fast Read0xEB指令为例标准库实现需关注以下技术细节// 标准库实现Quad I/O Fast Read uint32_t QSPI_QuadRead_STD(uint32_t addr, uint8_t *buffer, uint32_t size) { // 1. 配置CCR寄存器指令阶段 QUADSPI-CCR ~(QUADSPI_CCR_INSTRUCTION_Msk | QUADSPI_CCR_IMODE_Msk | QUADSPI_CCR_ADMODE_Msk | QUADSPI_CCR_DMODE_Msk); // 2. 设置Quad I/O Fast Read指令0xEB QUADSPI-CCR | (0xEB QUADSPI_CCR_INSTRUCTION_Pos) | (QSPI_CCR_IMODE_1_LINE QUADSPI_CCR_IMODE_Pos) | (QSPI_CCR_ADMODE_4_LINES QUADSPI_CCR_ADMODE_Pos) | (QSPI_CCR_DMODE_4_LINES QUADSPI_CCR_DMODE_Pos) | (6 QUADSPI_CCR_DCYC_Pos); // 6个dummy周期 // 3. 设置地址24位 QUADSPI-AR addr; // 4. 配置数据长度 QUADSPI-DLR size - 1; // 5. 启动传输并读取数据 for(uint32_t i 0; i size; i) { while(!(QUADSPI-SR QUADSPI_SR_FTF)); // 等待FIFO非空 buffer[i] *(volatile uint8_t*)QUADSPI-DR; } return size; }五、状态寄存器操作的差异实现博客中提到的状态寄存器配置在标准库中需通过间接模式实现// 标准库写状态寄存器以GD25Q64的QE位配置为例 void QSPI_WriteStatusReg_STD(uint8_t reg1, uint8_t reg2) { // 1. 发送写使能指令0x06 QSPI_SendCommand_STD(0x06, 0, 0, 0); // 2. 配置WRSR指令0x01 QUADSPI-CCR (0x01 QUADSPI_CCR_INSTRUCTION_Pos) | (QSPI_CCR_IMODE_1_LINE QUADSPI_CCR_IMODE_Pos) | (QSPI_CCR_DMODE_1_LINE QUADSPI_CCR_DMODE_Pos); // 3. 写入两个状态寄存器字节博客提到的关键点 QUADSPI-DLR 1; // 2字节数据 QUADSPI-DR reg1; while(!(QUADSPI-SR QUADSPI_SR_FTF)); QUADSPI-DR reg2; // 4. 等待写入完成 while(QSPI_GetFlagStatus(QUADSPI_FLAG_BUSY) SET); }六、标准库驱动的最佳实践建议时钟配置优化标准库需手动计算时钟分频确保QSPI时钟不超过闪存最大频率GD25Q64为104MHz。时序参数校准通过QUADSPI_DCR寄存器配置CSHT片选保持时间和CKMODE时钟模式匹配闪存时序要求。错误处理机制标准库缺乏自动错误恢复需实现超时检测和重试逻辑#define QSPI_TIMEOUT_MAX 100000 uint32_t timeout 0; while((QUADSPI-SR QUADSPI_SR_TCF) 0) { if(timeout QSPI_TIMEOUT_MAX) { // 超时处理复位QSPI外设 RCC_AHB3PeriphResetCmd(RCC_AHB3Periph_QSPI, ENABLE); RCC_AHB3PeriphResetCmd(RCC_AHB3Periph_QSPI, DISABLE); return ERROR_TIMEOUT; } }内存映射模式配置标准库需直接操作QUADSPI_CR的MM位和QUADSPI_LPTR寄存器// 进入内存映射模式 QUADSPI-CR | QUADSPI_CR_MM; // 使能内存映射 QUADSPI-LPTR 0x10; // 设置延迟周期 // 此时可通过0x90000000地址直接访问闪存标准库驱动虽然代码量较大但提供了更精细的时序控制和寄存器级访问能力适用于对性能要求苛刻或需要深度定制的应用场景。在迁移至HAL库时需特别注意状态机管理和中断处理机制的差异。参考来源STM32 QSPI接口驱动GD/W25Qxx配置简要

更多文章