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
相关产品推荐
相关产品推荐

