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

STM32H7+SAI+DMA双缓冲配置失败.

[复制链接]
Zzzzwq 提问时间:2025-8-23 11:38 / 未解决

我使用STM32H743IIT6配置了SAI1_blockA进行一个音频采集,然后配置了一个DMA进行数据搬运,开始我配置的DMA是手动模式,每次搬运完就进入中断,更换指针地址然后继续开始DMA搬运,但是这个方案在后期似有音频掉点的现象,所以现在想配置一个自动采集的双缓冲模式,使用的函数是HAL_DMAEx_MultiBufferStart_IT,但是就是驱动不起来,是否有大神可以指导一下? 以下是配置代码

int PLL2N_T = 393; 
int PLL2P_T = 32; 
int PLL2FRACN_T = 1770;

void MX_SAI1_Init(void)
{

  /* USER CODE BEGIN SAI1_Init 0 */

  /* USER CODE END SAI1_Init 0 */

  /* USER CODE BEGIN SAI1_Init 1 */

  /* USER CODE END SAI1_Init 1 */

  hsai_BlockA1.Instance = SAI1_Block_A;
  hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
  hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
  hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  hsai_BlockA1.Init.NoDivider = SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
  hsai_BlockA1.Init.Mckdiv = 1;
  hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
  hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
    hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_ENABLE;

  if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
  {
        printf("error.\r\n");
//    Error_Handler();
  }

    hsai_BlockA1.Init.Mckdiv = 1;

  // 最后再次调用 HAL_SAI_Init 来真正初始化硬件
  if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
  {
      printf("SAI init error.\r\n");
  }
}

void HAL_SAI_MspInit(SAI_HandleTypeDef* saiHandle)
{
HAL_StatusTypeDef state=0;
//  __HAL_RCC_DMAMUX1_CLK_ENABLE();
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* SAI1 */
    if(saiHandle->Instance==SAI1_Block_A)
    {
    /* SAI1 clock enable */

  /** Initializes the peripherals clock
  */
            PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
            PeriphClkInitStruct.PLL2.PLL2M = 1;
            PeriphClkInitStruct.PLL2.PLL2N = PLL2N_T;
            PeriphClkInitStruct.PLL2.PLL2P = PLL2P_T;
            PeriphClkInitStruct.PLL2.PLL2Q = 2;
            PeriphClkInitStruct.PLL2.PLL2R = 2;
            PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
            PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
            PeriphClkInitStruct.PLL2.PLL2FRACN = PLL2FRACN_T;
            PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
            if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
            {
                printf("PLL init fail.\r\n");
    //      Error_Handler();
            }

            if (SAI1_client == 0)
            {
                 __HAL_RCC_SAI1_CLK_ENABLE();

                /* Peripheral interrupt init*/
                HAL_NVIC_SetPriority(SAI1_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(SAI1_IRQn);
            }
            SAI1_client ++;

            /**SAI1_A_Block_A GPIO Configuration
            PE2     ------> SAI1_MCLK_A
            PE4     ------> SAI1_FS_A
            PE5     ------> SAI1_SCK_A
            PE6     ------> SAI1_SD_A
            */
            GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
            GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
            GPIO_InitStruct.Pull = GPIO_NOPULL;
            GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
            GPIO_InitStruct.Alternate = GPIO_AF6_SAI1;
            HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
            __HAL_RCC_DMA1_CLK_ENABLE();
            /* Peripheral DMA init*/

            hdma_sai1_a.Instance = DMA1_Stream0;
            hdma_sai1_a.Init.Request = DMA_REQUEST_SAI1_A;
            hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;
            hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
            hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
            hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
            hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
            hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
            hdma_sai1_a.Init.Priority = DMA_PRIORITY_VERY_HIGH;

            hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
            hdma_sai1_a.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
            hdma_sai1_a.Init.MemBurst = DMA_MBURST_SINGLE;
            hdma_sai1_a.Init.PeriphBurst = DMA_PBURST_SINGLE;

            HAL_DMA_RegisterCallback(&hdma_sai1_a,HAL_DMA_XFER_CPLT_CB_ID,dma_m0_rxcplt_callback);
            HAL_DMA_RegisterCallback(&hdma_sai1_a,HAL_DMA_XFER_M1CPLT_CB_ID,dma_m1_rxcplt_callback);

            if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK)
            {
                printf("SAI init fail.\r\n");
            }

//          HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)mem_info_ctr.Buffer1Pointer, 5120); //5632*4/1024 = 22

            __HAL_LINKDMA(saiHandle,hdmarx,hdma_sai1_a);

            HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
            HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

            state = HAL_DMAEx_MultiBufferStart_IT(&hdma_sai1_a, (uint32_t)&SAI1_Block_A->DR, (uint32_t)mem_info_ctr.Buffer1Pointer, (uint32_t)mem_info_ctr.Buffer2Pointer, 5120);/* 开启双缓冲 */
            if(state == HAL_OK)
            {
                printf("Multi config success.\r\n");
            }

    }
}
收藏 评论4 发布时间:2025-8-23 11:38

举报

4个回答
xmshao 回答时间:2025-8-25 14:31:58

你的DMA传输启动函数调用应该这样写:

HAL_DMAEx_MultiBufferStart_IT (&hdma_sai1_a,, (uint32_t)mem_info_ctr.Buffer1Pointer(uint32_t)&SAI1_Block_A->DR, (uint32_t)mem_info_ctr.Buffer2Pointer, 5120);

每传输5120个数据做缓冲切换。

Zzzzwq 回答时间:2025-8-27 18:38:21

xmshao 发表于 2025-8-25 14:31
你的DMA传输启动函数调用应该这样写:</p>
<p><strong>HAL_DMAEx_MultiBufferStart_IT</strong> (<code>&amp;hdma_sai1_a,</code>, `(uint3 ...

[md]好的,感谢回复,我去试一试

Zzzzwq 回答时间:2025-9-1 17:30:52

xmshao 发表于 2025-8-25 14:31
你的DMA传输启动函数调用应该这样写:</p>
<p><strong>HAL_DMAEx_MultiBufferStart_IT</strong> (<code>&amp;hdma_sai1_a,</code>, `(uint3 ...

[md]好像还是不行,我看很多人都是按照我那个函数使用的,好像并不是放中间把?

xmshao 回答时间:2025-9-2 08:17:38

Zzzzwq 发表于 2025-9-1 17:30
好像还是不行,我看很多人都是按照我那个函数使用的,好像并不是放中间把?
...

到底要怎样写,看看函数原型定义即可。

这里有类似文章可以参考下。

基于STM32H7 DMA 双缓冲实现SPI逐个数据输出

所属标签

相似问题

官网相关资源

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