CN / EN
文档反馈
感谢关注汇顶文档,期待您的宝贵建议!
感谢您的反馈,祝您愉快!

QSPI DMA SPI

QSPI DMA SPI示例实现了采用QSPI接口的外部Flash,读取Flash中的数据并通过SPI Master DMA方式传输数据。

QSPI DMA SPI示例的源代码和工程文件位于SDK_Folder\projects\peripheral\qspi\qspi_flash_dma_spim,其中工程文件在文件夹Keil_5下。

代码理解

示例工程流程图如图 37所示:

图 37 QSPI DMA SPI示例流程图
  1. 配置QSPI DMA SPI。
    g_qspi_handle.init.clock_prescaler = SystemCoreClock / 1000000;
    g_qspi_handle.init.clock_mode = QSPI_CLOCK_MODE_3;
    g_qspi_handle.init.rx_sample_delay = 0;
    
    hal_qspi_deinit(&g_qspi_handle);
    if (HAL_OK != hal_qspi_init(&g_qspi_handle))
    {
        printf("\r\nFlash initial failed.\r\n");
        return 0;
    }
    
    p_spi_handle->init.data_size          = SPI_DATASIZE_32BIT;
    p_spi_handle->init.clock_polarity     = SPI_POLARITY_LOW;
    p_spi_handle->init.clock_phase        = SPI_PHASE_1EDGE;
    p_spi_handle->init.baudrate_prescaler = SystemCoreClock / 1000000;
    p_spi_handle->init.ti_mode            = SPI_TIMODE_DISABLE;
    p_spi_handle->init.slave_select       = SPI_SLAVE_SELECT_0;
    hal_spi_deinit(p_spi_handle);
    hal_spi_init(p_spi_handle);
    1. 配置QSPI模块。

      配置QSPI的时钟为1 MHz,配置空闲状态时时钟信号为高电平。

    2. 配置SPI模块。
      • init.data_size:SPI数据发送宽度,可选择:SPI_DATASIZE_4BIT ~ SPI_DATASIZE_32BIT。
      • init.clock_polarity:SPI空闲状态时的时钟信号,可选择:SPI_POLARITY_LOW、SPI_POLARITY_HIGH。
      • init.clock_phase:SPI时钟切换的时间,可选择SPI_PHASE_1EDGE、SPI_PHASE_2EDGE。
      • baudrate_prescaler:SPI的时钟选择,此处为SystemCoreClock / 1000000即1 MHz;
      • init.ti_mode:SPI TI模式使能,可选择:SPI_TIMODE_DISABLE、SPI_TIMODE_ENABLE。
      • init.slave_select:SPI从设备的选择,可选择:SPI_SLAVE_SELECT_0、SPI_SLAVE_SELECT_1、SPI_SLAVE_SELECT_ALL。
  2. 调用hal_qspi_init()初始化QSPI模块。代码如下:
    hal_qspi_init(&g_qspi_handle);
  3. 调用SPI_FLASH_Read_Device_ID()获取Flash的设备ID。代码如下:
    device_id = SPI_FLASH_Read_Device_ID();
    printf("Read_Device_ID = 0x%06X\r\n", device_id);
    
  4. 调用SPI_FLASH_Page_Program()向Flash写数据。代码如下:
    printf("Page_Program...\r\n");
    SPI_FLASH_Page_Program(FLASH_PROGRAM_START_ADDR, flash_buffer);
    printf("Page Program Success.\r\n");
    
  5. 配置QSPI模式为SPI模式,配置数据位宽为32位,传输目的为EEPROM,输出大小为(FLASH_PAGE_SIZE >> 2) - 1。代码如下:
    /* Config QSPI in SPI mode, data size is 32bits */
    __HAL_QSPI_DISABLE(p_qspi_handle);
    ll_spi_set_frame_format(p_qspi_handle->p_instance, LL_SSI_FRF_SPI);
    ll_spi_set_data_size(p_qspi_handle->p_instance, LL_SSI_DATASIZE_32BIT);
    ll_spi_set_transfer_direction(p_qspi_handle->p_instance, LL_SSI_READ_EEPROM);
    ll_spi_set_receive_size(p_qspi_handle->p_instance, (FLASH_PAGE_SIZE >> 2) - 1);
    __HAL_QSPI_ENABLE(p_qspi_handle);
    
  6. 配置SPI为写模式。代码如下:
    /* Config SPI in write mode */
    __HAL_SPI_DISABLE(p_spi_handle);
    ll_spi_set_transfer_direction(p_spi_handle->p_instance, LL_SSI_SIMPLEX_TX);
    __HAL_SPI_ENABLE(p_spi_handle);
    
  7. 配置DMA burst length。代码如下:
    /* Config burst length of DMA */
    ll_dma_set_source_burst_length(DMA, p_qspi_handle->p_dma->channel, 
                                   LL_DMA_SRC_BURST_LENGTH_1);
    ll_dma_set_destination_burst_length(DMA, p_qspi_handle->p_dma->channel, 
                                        LL_DMA_DST_BURST_LENGTH_4);
    
  8. 开始DMA传输并等待传输完成。代码如下:
    /* Start read SPI flash */
    uint32_t cmd_addr = ((uint32_t)SPI_FLASH_CMD_READ << 24) | FLASH_PROGRAM_START_ADDR;
    hal_dma_start(p_qspi_handle->p_dma, (uint32_t)& p_qspi_handle->p_instance->DATA, (uint32_t)&
                  p_spi_handle->p_instance->DATA, FLASH_PAGE_SIZE >> 2);
    p_qspi_handle->p_instance->DATA = cmd_addr;
    __HAL_QSPI_ENABLE_DMARX(p_qspi_handle);
    __HAL_SPI_ENABLE_DMATX(p_spi_handle);
    hal_status_t status = hal_dma_poll_for_transfer(p_qspi_handle->p_dma, 1000);
    if (status == HAL_OK)
    {
        printf("Transfer finished.\r\n");
    }
    else
    {
        printf("Transfer failed, hal_status = %d\r\n", status);
    }
    

测试验证

  1. 用GProgrammer下载qspi_flash_dma_spim.bin至开发板。
  2. 将开发板串口连接至PC端,打开并配置GRUart。
  3. 在GRUart的Receive Data窗口中将会显示QSPI FLASH SPI数据的交互数据信息。

扫描关注

打开微信,使用“扫一扫”即可关注。