You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino Pro Portenta H7搭配MAX98357A的I2S DMA传输问题求助

问题解决思路与修正方案

核心问题诊断

当前代码中DMA流与I2S2的硬件映射不匹配,是导致DMA模式异常、死机的主要原因,同时存在初始化顺序、资源释放的逻辑漏洞。


具体解决步骤

1. 修正DMA流与I2S2的映射

Portenta H7的SPI2(I2S2)TX对应的DMA流是DMA1_Stream6,而非代码中的DMA1_Stream4(Stream4对应SPI3/I2S3 TX)。
修正代码:

hdma_i2s_tx.Instance = DMA1_Stream6 ; // 替换原DMA1_Stream4

2. 补充DMA中断配置

在DMA初始化完成后,添加中断优先级配置与启用逻辑,确保DMA传输的中断能被正确响应:

if (HAL_DMA_Init(&hdma_i2s_tx) != HAL_OK) {
  dmaError = HAL_DMA_GetError(&hdma_i2s_tx);
  Error_Handler();
}
// 新增DMA中断配置
HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);

3. 规范初始化流程(资源释放+顺序调整)

在每次初始化I2S/DMA前,先释放已占用的硬件资源,避免因重复初始化导致的资源冲突:

void I2S2_Prep_TX(unsigned long audioFreq)
{
  // 先释放原有资源,避免冲突
  HAL_I2S_DeInit(&hi2s2);
  HAL_DMA_DeInit(&hdma_i2s_tx);

  __HAL_RCC_DMA1_CLK_ENABLE();
  __HAL_RCC_SPI2_CLK_ENABLE(); // 手动启用SPI2时钟

  hdma_i2s_tx.Instance = DMA1_Stream6 ;
  hdma_i2s_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_i2s_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_i2s_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_i2s_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_i2s_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_i2s_tx.Init.Mode = DMA_CIRCULAR;
  hdma_i2s_tx.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_i2s_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

  if (HAL_DMA_Init(&hdma_i2s_tx) != HAL_OK) {
    dmaError = HAL_DMA_GetError(&hdma_i2s_tx);
    Error_Handler();
  }

  // 配置DMA中断
  HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);

  hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; // MAX98357A不需要MCLK,关闭以减少干扰
  hi2s2.Init.AudioFreq = audioFreq;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;
  hi2s2.Init.FirstBit = I2S_FIRSTBIT_MSB;
  hi2s2.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
  hi2s2.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_LEFT;
  hi2s2.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;

  hi2s2.hdmatx = &hdma_i2s_tx;
  
  if (HAL_I2S_Init(&hi2s2) != HAL_OK)
  {
    i2sError = HAL_I2S_GetError(&hi2s2);
    Error_Handler();
  }
}

4. 硬件适配优化

  • MAX98357A不需要MCLK信号,关闭I2S_MCLKOUTPUT_ENABLE可避免不必要的时序干扰
  • 确认Portenta H7与MAX98357A的引脚连线:
    • Portenta H7 PA4 → MAX98357A LRCLK(WS)
    • Portenta H7 PB10 → MAX98357A BCLK
    • Portenta H7 PB15 → MAX98357A DIN
    • 确保模块共地,电源供应稳定(MAX98357A支持3.3V/5V)

5. DMA传输调用规范

调用HAL_I2S_Transmit_DMA前,必须检查I2S状态是否就绪,避免返回HAL_BUSY错误:

if (HAL_I2S_GetState(&hi2s2) == HAL_I2S_STATE_READY) {
  HAL_I2S_Transmit_DMA(&hi2s2, _audioBuffer2, _audioBufferSize);
} else {
  // 处理未就绪情况:先停止当前传输再重启
  HAL_I2S_DMAStop(&hi2s2);
  HAL_I2S_Transmit_DMA(&hi2s2, _audioBuffer2, _audioBufferSize);
}

内容的提问来源于stack exchange,提问作者Electron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:52:07