STM32
直播中

李莉

7年用户 1444经验值
私信 关注
[问答]

STM32H7B0每次启动I2S发送数据,就出现一次破音是什么问题,如何解决?

功能描述:利用STM32H7B0的I2S(用DMA)接口发送数据给DAC(每秒发一次,一次持续发送100毫秒),发完数据后就停止I2S和DMA,等下一秒再启动发送数据。
存在的问题:每次启动I2S发送数据,就出现一次破音,请问这是什么问题,如何解决?
1、DMA配置如下:
// 初始化dmauint8 dma_i2s_init_dma(){    HAL_StatusTypeDef halFLag = HAL_ERROR;    // 使能dma时钟    __HAL_RCC_DMA1_CLK_ENABLE();    // 失能DMA-TX    HAL_DMA_DeInit( g_dmaTxHandle);    // 初始化DMA发送通道    g_dmaTxHandle.Instance = DMA1_Stream1;    g_dmaTxHandle.Init.Request = DMA_REQUEST_SPI1_TX;    // 请求源    g_dmaTxHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; // 存储器到外设    g_dmaTxHandle.Init.PeriphInc = DMA_PINC_DISABLE;    g_dmaTxHandle.Init.MemInc = DMA_MINC_ENABLE;    g_dmaTxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;    g_dmaTxHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;    g_dmaTxHandle.Init.Mode = DMA_NORMAL; // 普通模式    g_dmaTxHandle.Init.Priority = DMA_PRIORITY_MEDIUM;    g_dmaTxHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;    g_dmaTxHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; // 16字节    g_dmaTxHandle.Init.MemBurst = DMA_MBURST_INC4;              // 一次取16字节    g_dmaTxHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;    halFLag = HAL_DMA_Init( g_dmaTxHandle);    if (halFLag != HAL_OK)    {        return 0;    }    // 链接I2S句柄和Dma句柄    __HAL_LINKDMA( g_i2sHandle, hdmatx, g_dmaTxHandle);    // DMA中断使能    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);    return 1;}2、I2S配置如下(MCLK:12.288MHz,LRCK:48KHz):
// 初始化i2s外设uint8 dma_i2s_init_i2s(){    HAL_StatusTypeDef halFLag = HAL_ERROR;    dma_i2s_init_clock(); // 初始化时钟    dma_i2s_init_gpio();  // 初始化i2s的管脚    dma_i2s_init_dma();   // 初始化DMA    // 失能I2S    HAL_I2S_DeInit( g_i2sHandle);    // 组织I2S发送通信参数    g_i2sHandle.Instance = SPI1;                            // 复用SPI1    g_i2sHandle.Init.Mode = I2S_MODE_MASTER_TX;             // 主控制器    g_i2sHandle.Init.Standard = I2S_STANDARD_PHILIPS;       // 飞利浦协议    g_i2sHandle.Init.DataFormat = I2S_DATAFORMAT_24B;       // 24bit    g_i2sHandle.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;    // 主时钟输出    g_i2sHandle.Init.AudioFreq = I2S_AUDIOFREQ_48K;         // 采样率    g_i2sHandle.Init.CPOL = I2S_CPOL_LOW;                   // 空闲状态,时钟为低电平    g_i2sHandle.Init.FirstBit = I2S_FIRSTBIT_MSB;           // 大端模式,高字节在前    g_i2sHandle.Init.WSInversion = I2S_WS_INVERSION_ENABLE; // LRCK翻转,左低右高    g_i2sHandle.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_LEFT;    g_i2sHandle.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;    // 初始化I2S句柄    halFLag = HAL_I2S_Init( g_i2sHandle);    if (halFLag != HAL_OK)    {        return 0;    }    return 1;}3、停止DMA和I2S
// I2S发送完成的回调函数void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s){    __HAL_DMA_CLEAR_FLAG(hi2s, DMA_FLAG_TCIF1_5); // 清除中断标识    uint32 dwFactor = 4096;    uint32 dwFlag = 0;                                 // I2S发送完成标识符,非0标识发送完成    SPI_TypeDef *pSpi = (SPI_TypeDef *)hi2s->Instance; // SPI外设    // 等待i2s移位寄存器发送完成    while (1)    {        dwFlag = pSpi->SR   dwFactor;        if (dwFlag)        {            HAL_I2S_DMAStop(hi2s); // 停止I2S发送            g_byI2sCpltFlag = 0;   // 信号已发完            break;        }    }    return;}





回帖(1)

郑玉兰

2024-3-13 11:16:46
通常启动时产生的一次破音,可能有下面比较常见的两种情况:
1. 音源中存在有破音的信号, 可以跳过MCU来验证是否有破音产生。(换一个接口设备连接验证一下信号)
2. 功率转换时产生的,那么给功放延迟几十毫秒。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分