/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file quadspi.c * @brief This file provides code for the configuration * of the QUADSPI instances. ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "quadspi.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ QSPI_HandleTypeDef hqspi; /* QUADSPI init function */ void MX_QUADSPI_Init(void) { /* USER CODE BEGIN QUADSPI_Init 0 */ /* USER CODE END QUADSPI_Init 0 */ /* USER CODE BEGIN QUADSPI_Init 1 */ /* USER CODE END QUADSPI_Init 1 */ hqspi.Instance = QUADSPI; hqspi.Init.ClockPrescaler = 9; hqspi.Init.FifoThreshold = 4; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; hqspi.Init.FlashSize = 24; hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; if (HAL_QSPI_Init(&hqspi) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN QUADSPI_Init 2 */ /* USER CODE END QUADSPI_Init 2 */ } void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if(qspiHandle->Instance==QUADSPI) { /* USER CODE BEGIN QUADSPI_MspInit 0 */ /* USER CODE END QUADSPI_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI; PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_D1HCLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } /* QUADSPI clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK PB6 ------> QUADSPI_BK1_NCS */ GPIO_InitStruct.Pin = GPIO_PIN_6|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_AF9_QUADSPI; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; 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_QUADSPI; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; 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_QUADSPI; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_6; 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_QUADSPI; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN QUADSPI_MspInit 1 */ /* USER CODE END QUADSPI_MspInit 1 */ } } void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* qspiHandle) { if(qspiHandle->Instance==QUADSPI) { /* USER CODE BEGIN QUADSPI_MspDeInit 0 */ /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK PB6 ------> QUADSPI_BK1_NCS */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2|GPIO_PIN_6); /* USER CODE BEGIN QUADSPI_MspDeInit 1 */ /* USER CODE END QUADSPI_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ //QSPI发送命令 //instruction:要发送的指令 //address:发送到的目的地址 //dummyCycles:空指令周期数 // instructionMode:指令模式;QSPI_INSTRUCTION_NONE,QSPI_INSTRUCTION_1_LINE,QSPI_INSTRUCTION_2_LINE,QSPI_INSTRUCTION_4_LINE // addressMode:地址模式; QSPI_ADDRESS_NONE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_2_LINE,QSPI_ADDRESS_4_LINE // addressSize:地址长度;QSPI_ADDRESS_8_BITS,QSPI_ADDRESS_16_BITS,QSPI_ADDRESS_24_BITS,QSPI_ADDRESS_32_BITS // dataMode:数据模式; QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINE,QSPI_DATA_4_LINE void QSPI_Send_CMD(unsigned int instruction,unsigned int address,unsigned int dummyCycles,unsigned int instructionMode,unsigned int addressMode,unsigned int addressSize,unsigned int dataMode) { QSPI_CommandTypeDef Cmdhandler; Cmdhandler.Instruction=instruction; //指令 Cmdhandler.Address=address; //地址 Cmdhandler.DummyCycles=dummyCycles; //设置空指令周期数 Cmdhandler.InstructionMode=instructionMode; //指令模式 Cmdhandler.AddressMode=addressMode; //地址模式 Cmdhandler.AddressSize=addressSize; //地址长度 Cmdhandler.DataMode=dataMode; //数据模式 Cmdhandler.SIOOMode=QSPI_SIOO_INST_EVERY_CMD; //每次都发送指令 Cmdhandler.AlternateByteMode=QSPI_ALTERNATE_BYTES_NONE; //无交替字节 Cmdhandler.DdrMode=QSPI_DDR_MODE_DISABLE; //关闭DDR模式 Cmdhandler.DdrHoldHalfCycle=QSPI_DDR_HHC_ANALOG_DELAY; if(HAL_QSPI_Command(&hqspi,&Cmdhandler,5000) != HAL_OK) { Error_Handler(); } } //QSPI接收指定长度的数据 //buf:接收数据缓冲区首地址 //datalen:要传输的数据长度 //返回值:0,正常 // 其他,错误代码 unsigned char QSPI_Receive(unsigned char* buf,unsigned int datalen) { hqspi.Instance->DLR=datalen-1; //配置数据长度 if(HAL_QSPI_Receive(&hqspi,buf,5000)==HAL_OK) return 0; //接收数据 else return 1; } //QSPI发送指定长度的数据 //buf:发送数据缓冲区首地址 //datalen:要传输的数据长度 //返回值:0,正常 // 其他,错误代码 unsigned char QSPI_Transmit(unsigned char* buf,unsigned int datalen) { hqspi.Instance->DLR=datalen-1; //配置数据长度 if(HAL_QSPI_Transmit(&hqspi,buf,5000)==HAL_OK) return 0; //发送数据 else return 1; } /* USER CODE END 1 */