SPI_DMA 使用示例

例程路径: ls_sdk\examples\peripheral\spi_i2s\spi_dma_master ls_sdk\examples\peripheral\spi_i2s\spi_dma_slave

一、程序基本配置及说明:

spi_dma示例程序演示了使用DMA的方式实现spi master和spi slave之间的数据传输,例程以100ms的间隔传输10组数据

程序开始时先进行系统初始化和spi初始化:

    /* system init app     */
    sys_init_none();
    /* init spi and GPIO   */
    spi_init();

spi IO端口设置:

    /* Configure the GPIO AF */
    /* CLK-------------PB12 */	
    /* CS--------------PB13 */	
    /* MOSI------------PB14 */	
    /* MISO------------PB15 */
    /* master device */
    spi2_master_cs_init(SPI_CS_PIN);
    pinmux_spi2_master_clk_init(SPI_CLK_PIN,SPI_POLARITY_LOW);  // The idle state of clock must correspond to the polarity
    pinmux_spi2_master_mosi_init(SPI_MOSI_PIN); 
    pinmux_spi2_master_miso_init(SPI_MISO_PIN);
 
    /* slave device */
    pinmux_spi2_slave_clk_init(SPI_CLK_PIN);
    pinmux_spi2_slave_nss_init(SPI_CS_PIN);
    pinmux_spi2_slave_mosi_init(SPI_MOSI_PIN);
    pinmux_spi2_slave_miso_init(SPI_MISO_PIN);
   

二、操作步骤及结果:

2.1 操作步骤

说明

SPI初始化结构体配置说明:

    /* Set the SPI parameters */
    SpiHandle.Instance               = SPI2;   						        /*选择SPI Instance */
    SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;		    /*设置时钟分频因子,fpclk/分频数=fSCK */
    SpiHandle.Init.CLKPhase          = SPI_PHASE_1EDGE;				        /*设置时钟相位,可选奇/偶数边沿采样 */
    SpiHandle.Init.CLKPolarity       = SPI_POLARITY_LOW;				    /*设置时钟极性CPOL,可选高/低电平*/
    SpiHandle.Init.DataSize          = SPI_DATASIZE_8BIT;				    /*设置SPI的数据帧长度,可选8/16位 */
    SpiHandle.Init.FirstBit          = SPI_FIRSTBIT_MSB;				    /*设置MSB/LSB先行 */
    SpiHandle.Init.TIMode            = SPI_TIMODE_DISABLE;			        /*指定是否启用TI模式 */
    SpiHandle.Init.Mode 			 = SPI_MODE_MASTER;		                /*设置SPI的主/从机模式,可选主机/从机 */

SPI DMA模式数据传输提供了3个API:

HAL_SPI_Transmit_DMA:发送数据有效

HAL_SPI_Receive_DMA: 接收数据有效

HAL_SPI_TransmitReceive_DMA:发送和接收数据同时有效

HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi,void *Data,uint16_t Count)
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi,void *Data,uint16_t Count)
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi,void *TX_Data,void *RX_Data,uint16_t Count)

下面是HAL_SPI_TransmitReceive_DMA API中各参数的说明:

/**
  * @brief  Transmit and Receive an amount of data in non-blocking mode with DMA.
  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @param  TXData pointer to transmission data buffer
  * @param  RXData pointer to reception data buffer
  * @param  Count amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi,void *TX_Data,void *RX_Data,uint16_t Count)


数据传输完成时会调用callback函数:

/* master device */
void HAL_SPI_DMACpltCallback(SPI_HandleTypeDef *hspi) 
{
    SPI_CS_HIGH();
    /* Turn LED on: Transfer in transmission/reception process is correct */
    io_set_pin(LED_IO);
    ComState = COM_COMPLETE;
}

/* slave device */
void HAL_SPI_DMACpltCallback(SPI_HandleTypeDef *hspi) 
{
    /* Turn LED on: Transfer in transmission/reception process is correct */
    io_set_pin(LED_IO);
    ComState = COM_COMPLETE;
}

NOTE:

  1. LE501X的使用的数据buffer必须使用DMA_RAM_ATTR指定在DMA特定的RAM区域(参考spi dma例程)

  2. spi dma驱动程序使用收发一体的处理方式,因此在初始化DMA channel时必须配置发送和接收的channel

    (即使只使用transmit或receive也需要配置两个channel):

    static void spi_dma_channel_init(void)
    {
        DMA_CONTROLLER_INIT(dmac1_inst);
        SpiHandle.DMAC_Instance = &dmac1_inst;
        SpiHandle.Tx_Env.DMA.DMA_Channel = 0;
        SpiHandle.Rx_Env.DMA.DMA_Channel = 1;
    }
    

2.1.1 端口连接

例程需要使用两块开发板,在程序开始运行之前需要按照下面方式连接master和slave设备:

SPI MASTER BOARD

SPI SLAVE BOARD

spi_master_clk

spi_slave_clk

spi_master_cs

spi_slave_cs

spi_master_mosi

spi_slave_mosi

spi_master_miso

spi_slave_miso

GND

GND

2.1.2 运行程序

主从机程序分别编译后下载到对应的开发板中,需要先在从机上进行复位,然后在主机上进行复位后观察开发板上LED的状态

2.2 测试结果

在本例程中,aTxBuffer是预定义的,aRxBuffer大小与aTxBuffer相同。SPI主机通过HAL_SPI_TransmitReceive_DMA()发送aTxBuffer和接收RxBuffer的数据,同时SPI从机通过HAL_SPI_TransmitReceive_DMA()发送TxBuffer和接收RxBuffer的数据,通过Buffercmp()比较aRxBuffer和aTxBuffer,以检查buffer中数据的正确性。

板子上PA01对应的的LED可用于监控传输状态:

-当数据传输完成时LED会点亮

-当发送/接收过程中数据出现错误时,LED会以500ms的间隔闪烁