STM32 SPI+DMA (HAL库)使用方法

2 篇文章 0 订阅
/*
* SPI硬件初始化,内存地址初始化
*/
static void Init(void)
{
    uint8_t i;
    /*失能SPI1*/
    HAL_SPI_DeInit(&hspi1);

    /*清空FpgaRevData内存*/
    for(i=0;i<REV_MAX_NUM;i++)
    {
        memset(FpgaRevData[i],0,FPGA_DATA_PAKET_LENGTH);
    }
    /*初始化内存指针*/
    gWritePtr=0;
    gReadPtr=0;
    /*使能SPI1*/
    HAL_SPI_Init(&hspi1);
    /*SPI DMA初始化,并开启一次数据接收*/    
    HAL_SPI_Receive_DMA_INIT(&hspi1,FpgaRevData[gWritePtr],FPGA_DATA_PAKET_LENGTH);
}

/*
* SPI DMA初始化,并开启一次数据接收,
* 关键是返回函数的初始化,DMA 源地址和目的地址的初始化,各标志位的清空与开启
* 该程序修改与HAL库的HAL_SPI_Receive_DMA函数
*/
void HAL_SPI_Receive_DMA_INIT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
{
  hspi->State       = HAL_SPI_STATE_BUSY_RX;
  hspi->RxXferSize  = Size;

  /*Init field not used in handle to zero */
  hspi->RxISR       = NULL;

  /* Set the SPI Rx DMA transfer complete callback */
  hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;

  /* Enable the Rx DMA Stream */
  HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)(uint8_t *)pData, Size);

  /* Check if the SPI is already enabled */
  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
  }

  /* Enable the SPI Error Interrupt Bit */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);

  /* Enable Rx DMA Request */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
}


/*
* FPGA SPI1数据接收函数,一次接收6个字节数据包
* 该程序修改与HAL库的HAL_DMA_Start_IT函数和HAL_SPI_Receive_DMA函数
*/
__INLINE void FPGA_ReadBuffer(SPI_HandleTypeDef *hspi, uint8_t *DstAddress)
{
//  HAL_StatusTypeDef status = HAL_OK;

  /* calculate DMA base and stream number */
//  DMA_Base_Registers *regs = (DMA_Base_Registers *)(hspi->hdmarx)->StreamBaseAddress;

      /* Process locked */
//  __HAL_LOCK(hspi->hdmarx);
//  
//  if(HAL_DMA_STATE_READY == hspi->hdmarx->State)
//  {
    /* Change DMA peripheral state */
//    hspi->hdmarx->State = HAL_DMA_STATE_BUSY;

    /* Clear DBM bit */
    hspi->hdmarx->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);

    /* Configure DMA Stream destination address */
    hspi->hdmarx->Instance->M0AR = (uint32_t)(uint8_t *)DstAddress;

    /* Clear all interrupt flags at correct offset within the register */
//    regs->IFCR = 0x3FU << hspi->hdmarx->StreamIndex;

    /* Enable Common interrupts*/
    hspi->hdmarx->Instance->CR  |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME;
    hspi->hdmarx->Instance->FCR |= DMA_IT_FE;

    /* Enable the Peripheral */
    __HAL_DMA_ENABLE(hspi->hdmarx);
//  }
//  else
//  {
//    /* Process unlocked */
//    __HAL_UNLOCK(hspi->hdmarx);     
//    
//    /* Return error status */
//    status = HAL_BUSY;
//  }
      /* Check if the SPI is already enabled */
//  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
//  {
//    /* Enable SPI peripheral */
//    __HAL_SPI_ENABLE(hspi);
//  }

  /* Enable the SPI Error Interrupt Bit */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE|SPI_CR2_RXDMAEN);

//  /* Enable Rx DMA Request */
//  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);

//  return HAL_OK;
}



/*
*SPI 返回函数,打开SPI DMA开关,一次接收6个字节数据包
*/
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if(hspi==&hspi1)
    {           
        //HAL_SPI_DMAStop(hspi);//先关掉DMA
         /* Disable the SPI DMA Tx & Rx requests */
        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);//关掉DMA其实就是执行了这个操作
        if((gWritePtr + 1 == gReadPtr) || (gWritePtr == REV_MAX_NUM && gReadPtr == 0))//我的数据存储在一个二维数组中,这里判断满了
            return ;
        gWritePtr++;
        if (gWritePtr==REV_MAX_NUM) gWritePtr=0;        
        FPGA_ReadBuffer(hspi,FpgaRevData[gWritePtr]);       
    }
}

当SPI DMA硬件初始化(SPI DMA mode为DMA_NORMAL)后,就可以开始一次初始
化HAL_SPI_Receive_DMA_INIT,之后,当有数据到来,SPI接收完成返回函数会被调用,在返回函数中,首先关掉DMA,接收到数据后,提供下一次接收数据的地址,重新打开DMA。

  • 6
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32 HAL库实现SPI+DMA的步骤: 1. 配置SPI外设和DMA通道 ```c SPI_HandleTypeDef hspi; DMA_HandleTypeDef hdma_tx; void MX_SPI_Init(void) { /* SPI2 parameter configuration*/ hspi.Instance = SPI2; hspi.Init.Mode = SPI_MODE_MASTER; hspi.Init.Direction = SPI_DIRECTION_2LINES; hspi.Init.DataSize = SPI_DATASIZE_8BIT; hspi.Init.CLKPolarity = SPI_POLARITY_LOW; hspi.Init.CLKPhase = SPI_PHASE_1EDGE; hspi.Init.NSS = SPI_NSS_SOFT; hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi.Init.TIMode = SPI_TIMODE_DISABLE; hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi.Init.CRCPolynomial = 7; if (HAL_SPI_Init(&hspi) != HAL_OK) { Error_Handler(); } /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); /* DMA1_Channel5 init */ hdma_tx.Instance = DMA1_Channel5; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(&hspi, hdmatx, hdma_tx); } ``` 2. 配置DMA传输完成中断 ```c void DMA1_Channel5_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_tx); } ``` 3. 配置SPI发送函数 ```c uint8_t spi_tx_buf[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}; void spi_send_data_dma(void) { HAL_SPI_Transmit_DMA(&hspi, spi_tx_buf, 10); } ``` 4. 在主函数中调用spi_send_data_dma()函数即可实现SPI+DMA传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值