STM32 HAL C QuadSPI 显示读写

Posted

技术标签:

【中文标题】STM32 HAL C QuadSPI 显示读写【英文标题】:STM32 HAL C QuadSPI Display read and write 【发布时间】:2019-01-29 23:21:56 【问题描述】:

我使用 QSPI 不是连接内存,而是连接 FTDI 显示器。 我使用了 STM32CubeMX 和 Atollic TrueStudio。我包含了 FreeRTOS,但我还没有使用它。

使用 QuadSPI,我无法读取和写入 1、2 或 4 个字节,我在其中传输 3 个字节的内存地址。

如果我尝试读取这样的地址,它会在 HAL_QSPI_Receive 处超时,并且如果我配置,总线上不会生成任何信号

s_command.AddressMode    = QSPI_ADDRESS_1_LINE;

如果我配置

s_command.AddressMode    = QSPI_ADDRESS_NONE;

产生信号读取一个字节,但地址当然不发送。

为了在之后发送地址和接收字节,我在备用字节中发送地址。但是现在字节数可以是 1 或 2,但不是 4,因为我会再次超时。

我的代码片段

    uint8_t pData[4];
    uint32_t address = REG_ID;
    QspiReadData(address, 1, pData);

        uint32_t v = 0x12345678;
    pData[0] = v >> 24;
    pData[1] = (v >> 16) & 0xff;
    pData[2] = (v >> 8) & 0xff;
    pData[3] = v & 0xff;
        QspiWriteData(addr, 4, pData);

uint8_t QspiReadData(uint32_t address, uint32_t size, uint8_t* pData)

    QSPI_CommandTypeDef s_command;
    QSPI_AutoPollingTypeDef s_config;

    /* Initialize the read command */
    s_command.InstructionMode  = QSPI_INSTRUCTION_NONE;
    s_command.Instruction    = 0;
    s_command.AddressMode    = QSPI_ADDRESS_1_LINE;
    s_command.AddressSize    = QSPI_ADDRESS_32_BITS;
    s_command.Address      = address;
    s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    s_command.AlternateBytes   = 0;
    s_command.AlternateBytesSize = 0;
    s_command.DataMode      = QSPI_DATA_1_LINE; // QSPI_DATA_4_LINES
    s_command.DummyCycles    = 0;
    s_command.NbData       = size;
    s_command.DdrMode      = QSPI_DDR_MODE_DISABLE;
    s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    s_command.SIOOMode      = QSPI_SIOO_INST_EVERY_CMD;

    /* Configure the command */
    printf("HAL_QSPI_Command\n");
    if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
        printf("HAL_ERROR\n");
        return HAL_ERROR;
    

    /* Reception of the data */
    printf("HAL_QSPI_Receive\n");
    if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
        printf("HAL_ERROR\n"); // Timeout after 5000mS
        return HAL_ERROR;
    

    return HAL_OK;



/* QUADSPI init function */
void MX_QUADSPI_Init(void)


  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 254; /* 4 QSPI Freq= 108 MHz / (1+4) = 21.6 MHz */
  hqspi.Init.FifoThreshold = 1;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
  hqspi.Init.FlashSize = 0;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_8_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; // QSPI_CLOCK_MODE_0 Rising edge CPOL=0, QSPI_CLOCK_MODE_3 Falling edge CPOL=1
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  
    _Error_Handler(__FILE__, __LINE__);
  



uint8_t QspiWriteData(uint32_t address, uint32_t size, uint8_t* pData)

    QSPI_CommandTypeDef s_command;

    printf("Ft813QspiReadData8(%ld, %d, pData)\n", address, size);


    /* Initialize the read command */
    s_command.InstructionMode    = QSPI_INSTRUCTION_NONE;
    s_command.Instruction        = 0;
    s_command.AddressMode        = QSPI_ADDRESS_NONE;
    s_command.AddressSize        = QSPI_ADDRESS_24_BITS;
    s_command.Address            = 0;
    s_command.AlternateByteMode  = QSPI_ALTERNATE_BYTES_1_LINE;
    s_command.AlternateBytes     = address;
    s_command.AlternateBytesSize = QSPI_ALTERNATE_BYTES_24_BITS;
    s_command.DataMode           = QSPI_DATA_1_LINE;
    s_command.DummyCycles        = 0;
    s_command.NbData             = size;
    s_command.DdrMode            = QSPI_DDR_MODE_DISABLE;
    s_command.DdrHoldHalfCycle   = QSPI_DDR_HHC_ANALOG_DELAY;
    s_command.SIOOMode           = QSPI_SIOO_INST_EVERY_CMD;

    /* Configure the command */
    printf("HAL_QSPI_Command\n");
    if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
        printf("HAL_ERROR\n");
        return HAL_ERROR;
    

    /* Reception of the data */
    printf("HAL_QSPI_Transmit\n");
    if (HAL_QSPI_Transmit(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
        printf("HAL_ERROR\n");
        return HAL_ERROR;
    

    return HAL_OK;

可能是什么问题?


GPIO 引脚是这样配置的,以防它帮助其他人:

void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle)


  GPIO_InitTypeDef GPIO_InitStruct;
  if(qspiHandle->Instance==QUADSPI)
  
  /* USER CODE BEGIN QUADSPI_MspInit 0 */

  /* USER CODE END QUADSPI_MspInit 0 */
    /* QUADSPI clock enable */
    __HAL_RCC_QSPI_CLK_ENABLE();

    /**QUADSPI GPIO Configuration    
    PF6     ------> QUADSPI_BK1_IO3
    PF7     ------> QUADSPI_BK1_IO2
    PF8     ------> QUADSPI_BK1_IO0
    PF9     ------> QUADSPI_BK1_IO1
    PF10     ------> QUADSPI_CLK
    PB10     ------> QUADSPI_BK1_NCS 
    */
    GPIO_InitStruct.Pin = QUADSPI_BK1_IO3_Pin|QUADSPI_BK1_IO2_Pin|QUADSPI_CLK_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = QUADSPI_BK1_IO0_Pin|QUADSPI_BK1_IO1_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = QUADSPI_BK1_NCS_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(QUADSPI_BK1_NCS_GPIO_Port, &GPIO_InitStruct);

    /* QUADSPI DMA Init */
    /* QUADSPI Init */
    hdma_quadspi.Instance = DMA2_Stream2;
    hdma_quadspi.Init.Channel = DMA_CHANNEL_11;
    hdma_quadspi.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_quadspi.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_quadspi.Init.MemInc = DMA_MINC_ENABLE;
    hdma_quadspi.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_quadspi.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_quadspi.Init.Mode = DMA_NORMAL;
    hdma_quadspi.Init.Priority = DMA_PRIORITY_LOW;
    hdma_quadspi.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_quadspi) != HAL_OK)
    
      _Error_Handler(__FILE__, __LINE__);
    

    __HAL_LINKDMA(qspiHandle,hdma,hdma_quadspi);

    /* QUADSPI interrupt Init */
    HAL_NVIC_SetPriority(QUADSPI_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
  /* USER CODE BEGIN QUADSPI_MspInit 1 */

  /* USER CODE END QUADSPI_MspInit 1 */
  

【问题讨论】:

您似乎没有发布任何代码来启用 I/O 组并将相关 I/O 引脚置于 SPI 备用功能模式。如果有,请使用并编辑以包含它,如果没有,则需要先正确执行此操作,然后才能产生外部影响。 嗨,克里斯,你是对的。使用逻辑分析仪,我可以看到它在有限的情况下工作,所以我认为这将是一个问题,正如 gokhannnsahin 在下面指出的那样。无论如何,如果它可以帮助别人,就在这里。 【参考方案1】:

hqspi.Init.FlashSize = 0;是错的。 QuadSPI 模块需要学习将要写入/读取的设备的内存。将其更改为 31。它将运行。

【讨论】:

现在工作正常。不过我有一个问题,值 31,它是如何确定的? @user10155902 如果这解决了问题,您应该通过单击此帖子左侧的绿色复选标记将其标记为已接受的答案。还记得给所有有用的答案投票!

以上是关于STM32 HAL C QuadSPI 显示读写的主要内容,如果未能解决你的问题,请参考以下文章

STM32 从外部闪存引导,QUADSPI 引导加载程序

STM32“未定义对‘HAL_DELAY’的引用”

C++14 及以上版本的 stm32 hal 库警告

STM32STM32F429 HAL库开发模板注意事项

STM32 HAL I2C 轮询模式

STM32F4 HAL库开发 -- 工程模板解读