你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

32bit SPI使用DMA 初次不触发SPI中断 第二次发送不触发DMA中断

[复制链接]
talk is cheap 提问时间:2025-2-27 22:46 / 未解决

主控:STM32H750XBH6- ART-Pi

开发环境:CubeMX+MDK V5.27 问题背景: DAC芯片需要使用32bit SPI 目前使用轮询方式工作正常 需要硬件SPI+DMA加快速率 1.在仅仅更改:以下三项为8bit byte时,单字节的DMA发送是能够多次发送的,功能正常

hspi2.Init.DataSize = SPI_DATASIZE_32BIT;---------------->8BIT
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;------->BYTE
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;------>BYTE

2.当前代码使用HAL_SPI_Transmit_DMA()函数初次发送时,能够在逻辑分析仪上看到波形出现(能进入DMA中断),但是不进入SPI中断,导致SPI_Busy 3.当前代码由于处于Bus状态导致之后所有DMA发送直接返回

1.png

SPI配置项:

void MX_SPI2_Init(void)
{

/* USER CODE BEGIN SPI2_Init 0 */

/* USER CODE END SPI2_Init 0 */

/* USER CODE BEGIN SPI2_Init 1 */

/* USER CODE END SPI2_Init 1 */
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_32BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x0;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */

/* USER CODE END SPI2_Init 2 */

}

DMA配置项:

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(spiHandle->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspInit 0 */

  /* USER CODE END SPI2_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
    PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* SPI2 clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();

    __HAL_RCC_GPIOI_CLK_ENABLE();
    /**SPI2 GPIO Configuration
    PI1     ------> SPI2_SCK
    PI2     ------> SPI2_MISO
    PI3     ------> SPI2_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

    /* SPI2 DMA Init */
    /* SPI2_TX Init */
    hdma_spi2_tx.Instance = DMA1_Stream0;
    hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_spi2_tx.Init.Mode = DMA_NORMAL;
    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);

    /* SPI2 interrupt Init */
    HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);
  /* USER CODE BEGIN SPI2_MspInit 1 */

  /* USER CODE END SPI2_MspInit 1 */
  }
}
image.png
image.png
收藏 评论5 发布时间:2025-2-27 22:46

举报

5个回答
butterflyspring 回答时间:2025-2-28 12:17:41
似乎應該在DMA配置的這段代碼中有開啓 DMA發送完成的中斷。


樓主再檢查一下是否有這段代碼。

我在H723的板子上發現,如果不是能這個中斷,會有和你所說的一樣的現象發生。
xmshao 回答时间:2025-2-28 14:52:01
从你的描述来看,你基于基本配置应该没啥问题,尤其使用cubemx进行的话,你确认下传输长度对不对,长度别错了,不要发生越界访问。


按单字节传输不太容易错,反正两边都是一个对一个,长度也无须换算。


我这边做了验证确认,按字传输是没问题。我简单了做了两次Normal类型的DMA传输。


rrr.png


  hspi1.Init.DataSize = SPI_DATASIZE_32BIT;
   hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;


我使用STM32H743的SPI1 SPI2进行测试的,SPI2发送,SPI1结束,都用DMA完成搬运。


HAL_SPI_Receive_DMA(&hspi1, ( uint8_t *)RXstringx1, sizeof(TXstringx1)/4);


HAL_SPI_Transmit_DMA(&hspi2, ( uint8_t *)TXstringx1,  sizeof(TXstringx1)/4);


  HAL_Delay(500);

HAL_SPI_Receive_DMA(&hspi1, ( uint8_t *)RXstringx2, sizeof(TXstringx2)/4);


HAL_SPI_Transmit_DMA(&hspi2, ( uint8_t *)TXstringx2,  sizeof(TXstringx2)/4);
rrr.png
talk is cheap 回答时间:2025-3-2 14:55:41

xmshao 发表于 2025-2-28 14:52
从你的描述来看,你基于基本配置应该没啥问题,尤其使用cubemx进行的话,你确认下传输长度对不对,长度别错 ...

非常感谢您 已经找到bug-是确实传输长度的问题

问题有两点: 1.HAL_SPI_Transmit_DMA()这个函数的size似乎是以datawidth为单位的,不是以字节为单位的 在进行8bit和32bit 比对验证时刻 产生了指针越界 2.当时没能理解这部分代码:私自进行了修改,虽然属于无效代码



  /* Adjust XferCount according to DMA alignment / Data size */
  if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
  {
    if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
    {
      hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
    }
    if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
    {
      hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 3UL) >> 2UL;
    }
  }
  else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
  {
    if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
    {
      hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
    }
  }
  else 
  {
    /* Adjustment done */
    //**********************************************手动修改 无效代码*************************/
hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 3UL) >> 2UL;
  }
image.png
image.png
talk is cheap 回答时间:2025-3-2 14:57:18

butterflyspring 发表于 2025-2-28 12:17
似乎應該在DMA配置的這段代碼中有開啓 DMA發送完成的中斷。</p>
<p>

谢谢 当时也怀疑 中断开启操作等 但是看别人的中断回调函数没没做啥操作 可能ST已经封装的比较完善了

xmshao 回答时间:7 天前

talk is cheap 发表于 2025-3-2 14:55</p>
<p>非常感谢您 已经找到bug-是确实传输长度的问题

[md]嗯。

这个地方要注意。 有的STM32系列,DMA传输长度是按照源端的数据个数来统计的;

有点的系列比方STM32U5 H5这些,DMA传输长度是按照源端的数据个数及宽度转换为字节来计算的;

望周知~!

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版