你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

求助:STM32H7B0 + QSPI W25Q128JV无法读取ID

[复制链接]
TFX5200 提问时间:2025-5-10 11:57 / 未解决
最近用STM32H7B0 QSPI调试华邦的W25Q128JV Flash,调了一个多星期都没搞定,现在的问题是连读ID都读不出来。
从代码,到硬件,到芯片,各方面都已经反复确认,都没有发现问题,都不知道该怎么办了,甚至flash都换了好几颗。
有使用STM32H7B0 +QSPI调试成功的吗,希望能分享下,十分感激。



以下是我的OCTOSPI配置,配置成QSPI 4线模式,STM32CubeMX版本是v6.14
1.jpg 2.jpg

包括QSPI的的几个引脚,都反复确认过,没有问题,也量过芯片引脚到W25Q128芯片之间的通路,也是通的,芯片均无虚焊,换过好几个W25Q128芯片,问题都一样。


下面是读ID的函数,该函数移植的是反客的7B0代码,从W25Q64上改过来的,对比了一下,读取指令都一样,应该也没问题
3.jpg

程序是卡在HAL_OSPI_Command(&_hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)这个函数这里了,这个函数每次都返回1,1好像是操作错误。
正常应该是返回HAL_OK,但是每次都返回1的错误,不知道为什么这里会有问题。
这个函数HAL_OSPI_Command是发送指令到W25Q128芯片,应该发送失败了,我检查了硬件也没发现问题,不知道为什么老是配置失败。

读取ID 的指令,W25Q128JV的读取JEDECID的指令是0x9F, 其他配置都是用1线指令,1线数据去读,我反复对比和研究了配置,没看出有什么问题。

现在已经陷入僵局了,不知道还有什么方向,难道我换的几个flash都有问题?或者我的STM32H7B0也有问题?

希望用过STM32H7B0+QSPI W25Q128JV的大佬能给点方向,感谢
收藏 评论2 发布时间:2025-5-10 11:57

举报

2个回答
xmshao 回答时间:2025-5-12 11:26:03
你这样吧。你可以参考下STM32F7456DISC板的相关例程。它的例程里刚好就有针对25Q126的操作。


例程在这个地方: \STM32Cube_FW_F7_V1.17.2\Projects\STM32746G-Discovery\Applications\QSPI\QSPI_perfs
onlap 回答时间:2025-10-30 16:57:43

以下是在STM32H7A3(与STM32H7B0一样的只是内存大一些)成功运行QSPI W25Q128JV的代码

OSPI_HandleTypeDef hospi1; MDMA_HandleTypeDef hmdma_octospi1_fifo_th;

/ OCTOSPI1 init function / void MX_OCTOSPI1_Init(uint16_t ClockPrescaler) {

/ USER CODE BEGIN OCTOSPI1_Init 0 /

/ USER CODE END OCTOSPI1_Init 0 /

OSPIM_CfgTypeDef sOspiManagerCfg = {0};

/ USER CODE BEGIN OCTOSPI1_Init 1 /

/ USER CODE END OCTOSPI1_Init 1 / hospi1.Instance = OCTOSPI1; hospi1.Init.FifoThreshold = 4;// FIFO阈值为4个字节 空闲字节数 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;//禁止双闪存模式 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;//储存器类型 为标准协议MACRONIX hospi1.Init.DeviceSize = 24;// SPI FLASH大小,W25Q128大小为16M字节,2^24,所以取权值24-1=23 //QSPI_FLASH_SIZE - 1; 需要扩大一倍,否则内存映射方位最后 1 个地址时,会异常 hospi1.Init.ChipSelectHighTime =3;// 范围0-7片选高电平时间为3个时钟(106=60ns),即手册里面的参数tSHSL1=10nS tSHSL2=50nS hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;//自由运行时钟模式 hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; //模式0 片选信号为高的时候时钟为低电平 hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;//内存不支持卷读取 hospi1.Init.ClockPrescaler =ClockPrescaler; // QPSI分频比=280/(2+1)=93.333MHz,W25Q128最大频率为133M hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_HALFCYCLE;// 采样移位半个周期(DDR模式下,必须设置为0) hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;//DDR模式延期周期 无延迟 hospi1.Init.ChipSelectBoundary = 0;//芯片选择边界 单Flash模式(推荐设置为0) hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;//不使用时间延迟模块 hospi1.Init.MaxTran = 0;//最大传输字节数 DCR3 hospi1.Init.Refresh = 0;//禁用刷新率 DCR4 if (HAL_OSPI_Init(&hospi1) != HAL_OK)//函数内部包括引脚初始化void HAL_OSPI_MspInit(OSPI_HandleTypeDef ospiHandle) { Error_Handler(); }

//端口管理

sOspiManagerCfg.ClkPort = 1;//时钟引脚 sOspiManagerCfg.NCSPort = 1;//片选端口 sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW; sOspiManagerCfg.Req2AckTime = 1; if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { Error_Handler(); }

/ USER CODE BEGIN OCTOSPI1_Init 2 /

/ USER CODE END OCTOSPI1_Init 2 /

}

void HAL_OSPI_MspInit(OSPI_HandleTypeDef* ospiHandle) {

GPIO_InitTypeDef GPIO_InitStruct = {0}; if(ospiHandle->Instance==OCTOSPI1) { / USER CODE BEGIN OCTOSPI1_MspInit 0 /

/ USER CODE END OCTOSPI1_MspInit 0 /

LL_RCC_SetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE_HCLK);//280MHz

/ OCTOSPI1 clock enable / HAL_RCC_OCTOSPIM_CLK_ENABLE(); HAL_RCC_OSPI1_CLK_ENABLE();

HAL_RCC_GPIOA_CLK_ENABLE(); HAL_RCC_GPIOC_CLK_ENABLE(); /*OCTOSPI1 GPIO Configuration PA1 ------> OCTOSPIM_P1_IO3 PA3 ------> OCTOSPIM_P1_CLK PA7 ------> OCTOSPIM_P1_IO2 PC9 ------> OCTOSPIM_P1_IO0 PC10 ------> OCTOSPIM_P1_IO1 PC11 ------> OCTOSPIM_P1_NCS / GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF3_OCTOSPIM_P1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPIM_P1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/ OCTOSPI1 MDMA Init / / MDMA controller clock enable / __HAL_RCC_MDMA_CLK_ENABLE(); HAL_MDMA_DeInit(&hmdma_octospi1_fifo_th);

/ OCTOSPI1 MDMA Init / // OCTOSPI1_FIFO_TH Init hmdma_octospi1_fifo_th.Instance = MDMA_Channel0; // 使用MDMA的通道0 hmdma_octospi1_fifo_th.Init.Request = MDMA_REQUEST_OCTOSPI1_FIFO_TH; // QSPI的FIFO阀值触发中断 hmdma_octospi1_fifo_th.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER; // 使用MDMA的buffer传输 hmdma_octospi1_fifo_th.Init.Priority = MDMA_PRIORITY_VERY_HIGH; // 优先级高 hmdma_octospi1_fifo_th.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;// 小端格式 hmdma_octospi1_fifo_th.Init.SourceInc = MDMA_SRC_INC_DISABLE;// BYTE;// // 源地址字节不递增 hmdma_octospi1_fifo_th.Init.DestinationInc = MDMA_DEST_INC_BYTE; // 目的地址自增 hmdma_octospi1_fifo_th.Init.SourceDataSize = MDMA_SRC_DATASIZE_BYTE; // 源地址数据宽度字节 hmdma_octospi1_fifo_th.Init.DestDataSize = MDMA_DEST_DATASIZE_BYTE;// 目的地址数据宽度字节 hmdma_octospi1_fifo_th.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; // 小端,右对齐 hmdma_octospi1_fifo_th.Init.BufferTransferLength = 128; // 每次传输1个字节 hmdma_octospi1_fifo_th.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE; // 源数据单次传输 hmdma_octospi1_fifo_th.Init.DestBurst = MDMA_DEST_BURST_SINGLE; // 目的数据单次传输 hmdma_octospi1_fifo_th.Init.SourceBlockAddressOffset = 0; // 用于block传输,buffer传输用不到 hmdma_octospi1_fifo_th.Init.DestBlockAddressOffset = 0; // 用于block传输,buffer传输用不到

if (HAL_MDMA_Init(&hmdma_octospi1_fifo_th) != HAL_OK)//初始化 { Error_Handler(); }

if (HAL_MDMA_ConfigPostRequestMask(&hmdma_octospi1_fifo_th, 0, 0) != HAL_OK)// { Error_Handler(); }

__HAL_LINKDMA(ospiHandle,hmdma,hmdma_octospi1_fifo_th);

/ OCTOSPI1 interrupt Init / HAL_NVIC_SetPriority(OCTOSPI1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(OCTOSPI1_IRQn);

// / Clear all interrupt flags / // HAL_MDMA_CLEAR_FLAG(&hmdma_octospi1_fifo_th, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC)); //
//// / Clear the Channel Transfer Complete flag / ////
HAL_MDMA_CLEAR_FLAG(&hmdma_octospi1_fifo_th, MDMA_FLAG_CTC);

// / Enable the Peripheral / // __HAL_MDMA_ENABLE(&hmdma_octospi1_fifo_th);

} }

void HAL_OSPI_MspDeInit(OSPI_HandleTypeDef* ospiHandle) {

if(ospiHandle->Instance==OCTOSPI1) { / USER CODE BEGIN OCTOSPI1_MspDeInit 0 /

/ USER CODE END OCTOSPI1_MspDeInit 0 / / Peripheral clock disable / HAL_RCC_OCTOSPIM_CLK_DISABLE(); HAL_RCC_OSPI1_CLK_DISABLE();

/*OCTOSPI1 GPIO Configuration PA1 ------> OCTOSPIM_P1_IO3 PA3 ------> OCTOSPIM_P1_CLK PA7 ------> OCTOSPIM_P1_IO2 PC9 ------> OCTOSPIM_P1_IO0 PC10 ------> OCTOSPIM_P1_IO1 PC11 ------> OCTOSPIM_P1_NCS / HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_7);

HAL_GPIO_DeInit(GPIOC, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11);

/ OCTOSPI1 MDMA DeInit / HAL_MDMA_DeInit(ospiHandle->hmdma);

/ OCTOSPI1 interrupt Deinit / HAL_NVIC_DisableIRQ(OCTOSPI1_IRQn); / USER CODE BEGIN OCTOSPI1_MspDeInit 1 /

/ USER CODE END OCTOSPI1_MspDeInit 1 / } }

/ USER CODE BEGIN 1 /

extern MDMA_HandleTypeDef hmdma_octospi1_fifo_th; extern OSPI_HandleTypeDef hospi1;

/ 本文件使用的全局变量 / static __IO uint8_t rx_Completed,tx_Completed,cmd_Completed,status_Match;//,timeout;

/ USER CODE BEGIN 1 / / HAL_QSPI_Init HAL_QSPI_DeInit HAL_QSPI_Command HAL_QSPI_Command_IT HAL_QSPI_AutoPolling HAL_QSPI_AutoPolling_IT HAL_QSPI_Transmit HAL_QSPI_Receive HAL_QSPI_Transmit_DMA HAL_QSPI_Receive_DMA HAL_QSPI_MemoryMapped / /**

  • @brief 初始化OSPI存储器
  • @retval OSPI存储器状态 */

uint8_t W25Qxx_OSPI_Init(uint16_t ClockPrescaler) { OSPI_RegularCmdTypeDef s_command; uint16_t w25qxx_id; uint8_t value = W25QxJV_FSR_QE; // GPIO_InitTypeDef GPIO_InitStruct;

// LL_RCC_SetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE_HCLK);//280MHz

// / OCTOSPI1 clock enable / // HAL_RCC_OCTOSPIM_CLK_ENABLE(); // HAL_RCC_OSPI1_CLK_ENABLE();

// HAL_RCC_GPIOA_CLK_ENABLE(); // HAL_RCC_GPIOC_CLK_ENABLE(); // /*OCTOSPI1 GPIO Configuration // PA1 ------> OCTOSPIM_P1_IO3 // PA3 ------> OCTOSPIM_P1_CLK // PA7 ------> OCTOSPIM_P1_IO2 // PC9 ------> OCTOSPIM_P1_IO0 // PC10 ------> OCTOSPIM_P1_IO1 // PC11 ------> OCTOSPIM_P1_NCS // / // GPIO_InitStruct.Pin = GPIO_PIN_1; // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1; // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// GPIO_InitStruct.Pin = GPIO_PIN_3; // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // GPIO_InitStruct.Alternate = GPIO_AF3_OCTOSPIM_P1; // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// GPIO_InitStruct.Pin = GPIO_PIN_7; // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPIM_P1; // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11; // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1; // HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// // OSPIM_CfgTypeDef sOspiManagerCfg = {0};

// / USER CODE BEGIN OCTOSPI1_Init 1 /

// / USER CODE END OCTOSPI1_Init 1 /

// hospi1.Instance = OCTOSPI1; // hospi1.Init.FifoThreshold = 4;// FIFO阈值为4个字节 空闲字节数 // hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;//禁止双闪存模式 // hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;//储存器类型 为标准协议MACRONIX // hospi1.Init.DeviceSize = 23;// SPI FLASH大小,W25Q128大小为16M字节,2^24,所以取权值24-1=23 // hospi1.Init.ChipSelectHighTime =3;// 范围0-7片选高电平时间为3个时钟(10*6=60ns),即手册里面的参数tSHSL1=10nS tSHSL2=50nS // hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;//自由运行时钟模式 // hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; //模式0 片选信号为高的时候时钟为低电平 // hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;//内存不支持卷读取 // hospi1.Init.ClockPrescaler =ClockPrescaler; // QPSI分频比=280/(2+1)=93.333MHz,W25Q128最大频率为133M // hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_HALFCYCLE;// 采样移位半个周期(DDR模式下,必须设置为0) // hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;//DDR模式延期周期 无延迟 // hospi1.Init.ChipSelectBoundary = 0;//芯片选择边界 单Flash模式(推荐设置为0) // hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;//不使用时间延迟模块 // hospi1.Init.MaxTran = 0;//最大传输字节数 DCR3 // hospi1.Init.Refresh = 0;//禁用刷新率 DCR4 // if (HAL_OSPI_Init(&hospi1) != HAL_OK) // { // Error_Handler(); // }

// //端口管理 // OSPIM_CfgTypeDef sOspiManagerCfg = {0}; // sOspiManagerCfg.ClkPort = 1;//时钟引脚 // sOspiManagerCfg.NCSPort = 1;//片选端口 // sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW; // sOspiManagerCfg.Req2AckTime = 1; // if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) // { // Error_Handler(); // }

/* OSPI存储器复位 */

if (W25Qxx_OSPI_ResetMemory() != OSPI_OK) { return OSPI_NOT_SUPPORTED; }

/ 使能写操作 / if (W25Qxx_OSPI_WriteEnable() != OSPI_OK) { return OSPI_ERROR; } / 设置四路使能的状态寄存器,使能四通道IO2和IO3引脚 / /*

  • @brief QSPI发送命令

  • @param cmd : 要发送的指令

  • @param addr: 发送到的目的地址

  • @param mode: 模式,详细位定义如下:

  • @arg mode[1:0]: 指令模式; 00,无指令; 01,单线传输指令; 10,双线传输指令; 11,四线传输指令.

  • @arg mode[3:2]: 地址模式; 00,无地址; 01,单线传输地址; 10,双线传输地址; 11,四线传输地址.

  • @arg mode[5:4]: 地址长度; 00,8位地址; 01,16位地址; 10,24位地址; 11,32位地址.

  • @arg mode[7:6]: 数据模式; 00,无数据; 01,单线传输数据; 10,双线传输数据; 11,四线传输数据.

  • @param dmcycle: 空指令周期数

    / s_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;//工作模式配置 s_command.FlashId = HAL_OSPI_FLASH_ID_1;// 第一片flash s_command.Instruction = WRITE_STATUS_REG2_CMD; //指令0x31 W25Q128指令 s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;//指令模式 s_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;//8bit数据 s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;//单通道模式 // s_command.Address = 0x000; s_command.AddressMode = HAL_OSPI_ADDRESS_NONE; // 地址模式 // s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS; s_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;//单通道模式 // s_command.AlternateBytes = 0xFFFFFFFF; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;//无交替字节 // s_command.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS; // s_command.AlternateBytesDtrMode=HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; s_command.DataMode = HAL_OSPI_DATA_1_LINE; // 数据模式 s_command.NbData = 1;//1字节数据0-0xFFFFFFFF 0=整个储存器 s_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; s_command.DummyCycles = 0; // 设置空指令周期数0-31 s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; // 每次都发送指令 s_command.DQSMode = HAL_OSPI_DQS_DISABLE;//不使用DQS / 配置命令 / if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return OSPI_ERROR; } / 传输数据 / if (HAL_OSPI_Transmit(&hospi1, &value, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return OSPI_ERROR; } / 自动轮询模式等待存储器就绪 / if (W25Qxx_OSPI_AutoPollingMemReady(W25QxJV_SUBSECTOR_ERASE_MAX_TIME) != OSPI_OK) { return OSPI_ERROR; } w25qxx_id=W25Qxx_OSPI_FLASH_ReadDeviceID(); / 配置地址模式为 4 字节 , 非W25Q256直接跳过*/ if ( w25qxx_id!= W25Q256) return OSPI_OK;

    if (W25Qxx_OSPI_Addr_Mode_Init() != OSPI_OK) { return OSPI_ERROR; }

    return OSPI_OK; }

/**

  • @brief 检查地址模式不是4字节地址,配置为4字节

  • @retval OSPI存储器状态 */ uint8_t W25Qxx_OSPI_Addr_Mode_Init(void) { OSPI_RegularCmdTypeDef s_command; uint8_t reg;

    / 初始化读取状态寄存器命令 / s_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; s_command.FlashId = HAL_OSPI_FLASH_ID_1; s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_STATUS_REG3_CMD;//WRITE_STATUS_REG3_CMD;//寄存器3 s_command.AddressMode = HAL_OSPI_ADDRESS_NONE; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = HAL_OSPI_DATA_1_LINE; s_command.DummyCycles = 0; s_command.NbData = 1; s_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; s_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; s_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; s_command.DQSMode = HAL_OSPI_DQS_DISABLE;

    / 配置命令 / if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return OSPI_ERROR; } / 接收数据 / if (HAL_OSPI_Receive(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return OSPI_ERROR; }

    / 检查寄存器的值 / if ((reg & W25Q256FV_FSR_4ByteAddrMode) == 1) // 4字节模式 { return OSPI_OK; } else // 3字节模式 { / 配置进入 4 字节地址模式命令 / s_command.Instruction = Enter_4Byte_Addr_Mode_CMD;// s_command.DataMode = HAL_OSPI_DATA_NONE;

    / 配置并发送命令 / if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)//寄存器3 地址模式 != HAL_OK) { return OSPI_ERROR; }

    / 自动轮询模式等待存储器就绪 / if (W25Qxx_OSPI_AutoPollingMemReady( W25QxJV_SUBSECTOR_ERASE_MAX_TIME) != OSPI_OK) { return OSPI_ERROR; }

    return OSPI_OK; } } /*** @brief 从OSPI存储器中读取大量数据.

  • @param pData: 指向要读取的数据的指针

  • @param ReadAddr: 读取起始地址

  • @param Size: 要读取的数据大小

  • @retval OSPI存储器状态 / uint8_t W25Qxx_OSPI_Read(uint8_t pData, uint32_t ReadAddr, uint32_t Size) { OSPI_RegularCmdTypeDef s_command;

    if(Size == 0) return OSPI_OK;

    / 初始化读命令 / s_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; s_command.FlashId = HAL_OSPI_FLASH_ID_1; s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;//指令1线 s_command.Instruction = QUAD_INOUT_FAST_READ_CMD;//快速读命令 s_command.AddressMode = HAL_OSPI_ADDRESS_4_LINES;//地址4线

    if W25Qxx_ID==W25Q256

    s_command.AddressSize = HAL_OSPI_ADDRESS_32_BITS;

    else

    s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;//24位地址

    endif

    s_command.Address = ReadAddr; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = HAL_OSPI_DATA_4_LINES;//数据4线 s_command.DummyCycles = 6; s_command.NbData = Size; s_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; s_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; s_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; s_command.DQSMode = HAL_OSPI_DQS_DISABLE;

    / 配置命令 / if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)//发送快速读命令 != HAL_OK) { return OSPI_ERROR; }

    / 接收数据 / if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)!= HAL_OK) { return OSPI_ERROR;

    }

    return OSPI_OK; }

/**

  • @brief 读取FLASH Device ID

  • @param 无

  • @retval FLASH Device ID / uint32_t W25Qxx_OSPI_FLASH_ReadDeviceID(void) { OSPI_RegularCmdTypeDef s_command; uint32_t Temp = 0; uint8_t pData[3]; /##-2-读取设备ID测试 ###########################################/ / 读取制造/设备 ID */ s_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; s_command.FlashId = HAL_OSPI_FLASH_ID_1; s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_ID_CMD; s_command.AddressMode = HAL_OSPI_ADDRESS_1_LINE; s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS; s_command.Address = 0x000000; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = HAL_OSPI_DATA_1_LINE; s_command.DummyCycles = 0; s_command.NbData = 2; s_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; s_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; s_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; s_command.DQSMode = HAL_OSPI_DQS_DISABLE;

    HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

    HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

    Temp = pData[1] | (pData[0] << 8);

    return Temp; }

/**

  • @brief 读取存储器的SR并等待EOP

  • @param hOSPI: OSPI句柄

  • @param Timeout 超时

  • @retval 无 / uint8_t W25Qxx_OSPI_AutoPollingMemReady(uint32_t Timeout) { OSPI_RegularCmdTypeDef s_command; OSPI_AutoPollingTypeDef s_config; / 配置自动轮询模式等待存储器准备就绪 */ s_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; s_command.FlashId = HAL_OSPI_FLASH_ID_1; s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_STATUS_REG1_CMD;//读寄存器1 s_command.AddressMode = HAL_OSPI_ADDRESS_NONE; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = HAL_OSPI_DATA_1_LINE; s_command.DummyCycles = 0; s_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; s_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; s_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; s_command.DQSMode = HAL_OSPI_DQS_DISABLE;

    if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)//读寄存器1 != HAL_OK) { return OSPI_ERROR; }

    s_config.Match = 0x00;//匹配数据 s_config.Mask = W25QxJV_FSR_BUSY;//寄存器第1位 s_config.MatchMode = HAL_OSPI_MATCH_MODE_AND;//逻辑与判断 完全匹配 s_config.Interval = 0x10;//查询间隔时间0-0xFFFF CLK周期 s_config.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE;//匹配后自动停止检测

    if (HAL_OSPI_AutoPolling(&hospi1, &s_config, Timeout) != HAL_OK)//配置自动轮询模式 { return OSPI_ERROR; } return OSPI_OK; }

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版