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

STM32 I²S(DMA)采集经USB CDC输出出现阶跃失真问题求助

问题分析与解决办法

核心排查前提

逻辑分析仪显示I²S信号正常,说明CS5343输出、I²S物理链路无问题,故障集中在STM32的I²S DMA采集、数据格式处理、USB CDC传输三个环节。


1. DMA与USB CDC的缓冲区同步冲突

原因

I²S DMA是连续高速采集,USB CDC受总线调度限制为批量传输,若使用单缓冲区,DMA写入新数据时会覆盖未发送的旧数据,导致采样点丢失/错乱,表现为阶跃失真。

解决办法

启用双缓冲机制,彻底隔离采集与发送的内存操作:

#define BUF_LEN 512
uint32_t i2s_dma_buf[2][BUF_LEN];
volatile uint8_t active_buf = 0;
volatile uint8_t buf0_ready = 0, buf1_ready = 0;

// I²S DMA接收完成回调
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
    // 标记当前缓冲区为可发送状态
    if(active_buf == 0) buf0_ready = 1;
    else buf1_ready = 1;
    // 切换缓冲区继续采集
    active_buf ^= 1;
    HAL_I2S_Receive_DMA(hi2s, i2s_dma_buf[active_buf], BUF_LEN);
}

// USB CDC发送完成回调
void HAL_CDC_TxCpltCallback(CDC_HandleTypeDef *hcdc) {
    // 仅发送已就绪的缓冲区
    if(buf0_ready) {
        buf0_ready = 0;
        HAL_CDC_Transmit_DMA(hcdc, (uint8_t*)i2s_dma_buf[0], BUF_LEN*4);
    } else if(buf1_ready) {
        buf1_ready = 0;
        HAL_CDC_Transmit_DMA(hcdc, (uint8_t*)i2s_dma_buf[1], BUF_LEN*4);
    }
}
  • 确保DMA传输长度是USB最大包长(通常64字节)的整数倍,避免半帧数据截断。

2. 数据格式转换错误(补码/右移处理失误)

原因

CS5343输出24位补码,常见错误包括:

  • 用uint32_t存储后直接右移(逻辑右移清零符号位,负数变为正数);
  • 未做符号扩展,24位补码转32位时高位填充0而非符号位;
  • 字节序错误(CS5343大端输出,STM32小端存储,发送时未调整)。

解决办法

用带符号类型处理补码,确保算术右移与字节序正确:

// 假设DMA采集的是24位左对齐补码(存于uint32_t)
int32_t raw_sample = (int32_t)(i2s_dma_buf[buf_idx][sample_idx] << 8); // 符号扩展为32位
int32_t processed_sample = raw_sample >> 1; // 算术右移1位,保留符号

// 转USB发送的小端字节序
uint8_t usb_byte[3];
usb_byte[0] = processed_sample & 0xFF;
usb_byte[1] = (processed_sample >> 8) & 0xFF;
usb_byte[2] = (processed_sample >> 16) & 0xFF;

3. I²S配置的隐藏对齐问题

原因

逻辑信号正常不代表STM32接收配置完全匹配:

  • I²S帧格式不匹配:CS5343默认是标准I²S格式(WS在第一个数据位前的时钟沿切换),若STM32设为左/右对齐,会导致数据错位;
  • DMA传输宽度与I²S数据宽度不匹配:比如I²S设为24位,DMA设为32位但未处理对齐逻辑,导致内存中数据偏移。

解决办法

  • 核对STM32 I²S寄存器配置:
    • I2S_CR1.I2SSTD设为I2S_STANDARD_PHILIPS;
    • I2S_CR2.DATLEN设为I2S_DATLEN_24B,DMA传输宽度设为DMA_DATA_WIDTH_WORD;
  • 跳过USB环节,直接通过USART打印DMA缓冲区的原始数据,对比逻辑分析仪抓取的数值,验证采集数据是否正确。

4. USB CDC数据包拆分问题

原因

USB CDC批量端点最大包长为64字节,若单个采样点的字节被拆分到两个数据包中,接收端未正确拼接会导致数据错乱。

解决办法

  • 调整DMA缓冲区大小为64字节的整数倍,减少跨包概率;
  • 在接收端实现数据包拼接逻辑,确保采样点的字节完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 14:18:18