PDM协议---音频数据接收

PDM协议基础

什么是PDM?
  • PDM(Pulse Density Modulation脉冲密度调制 是一种通过脉冲密度表示模拟信号幅度的数字调制方式。

  • 核心原理

    • 麦克风将模拟信号(声音)转换为 单比特数据流,每个时钟周期输出1位(0或1)。

    • 数据流中 1的密度 反映输入信号的幅度(例如:高密度1 = 高电压,低密度1 = 低电压)。

PDM vs PCM 
特性PDMPCM(脉冲编码调制)
数据形式单比特流(1位/时钟周期)多比特样本(如16位/样本)
转换方式直接输出密度调制信号需采样、量化、编码
应用场景数字麦克风、低功耗设备音频存储、高保真音频处理
PDM数据格式

时钟与数据关系

时钟与数据关系
  • PDM数据流 由 时钟(CLK) 和 数据(DATA) 信号组成:

    • CLK:主控生成的方波时钟(如2 MHz)。

    • DATA:在每个时钟周期输出1位(0或1),密度反映信号幅度。

  • (2) ASCII时序图
    CLK  : _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_  (2 MHz方波)
    DATA : 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 1  (示例数据流)
    采样点: ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑  (在CLK上升沿采样DATA)
  • 上升沿采样:通常在时钟上升沿读取数据位。

  • 数据密度:在固定时间段内,统计1的数量(例如:8个时钟周期内有5个1 → 表示高电平)

PDM麦克风硬件连接

典型电路
PDM麦克风引脚物奇7036连接说明
VDD3.3V/1.8V电源(需电平匹配)
GNDGND共地
CLKGPIO_PDM_CLK主控输出的时钟信号
DATAGPIO_PDM_DATA麦克风输出的数据流
注意事项
  • 时钟频率:常见1–3.2 MHz(需参考麦克风规格书)。

  • 电平匹配:确保麦克风与主控的电压域一致(如1.8V或3.3V)。

  • 去耦电容:在VDD和GND之间添加0.1μF电容,减少电源噪声。

 上手Demo(基于物奇7036)

目标:配置PDM接口,采集数据并转换为PCM格式。
(1) 硬件初始化
#include "wq7036_pdm.h"  // 物奇7036的PDM驱动头文件

// 定义PDM缓冲区
#define PDM_BUFFER_SIZE  256
uint16_t pdm_buffer[PDM_BUFFER_SIZE];
int16_t pcm_buffer[PDM_BUFFER_SIZE];  // 转换后的PCM数据

void pdm_init() {
    // 1. 使能PDM外设时钟
    CLK_EnablePDM(true);

    // 2. 配置GPIO复用为PDM功能
    GPIO_SetFunc(GPIO_PDM_CLK, GPIO_FUNC_PDM_CLK);
    GPIO_SetFunc(GPIO_PDM_DATA, GPIO_FUNC_PDM_DATA);

    // 3. 配置PDM控制器
    PDM_Config_t pdm_cfg = {
        .mode = PDM_MASTER,           // 主模式(输出时钟)
        .clk_freq = 2000000,          // 2 MHz时钟
        .sample_rate = 16000,         // 16 kHz采样率
        .data_width = 16,             // 16位数据
        .osr = 64,                    // 过采样率(OSR=64)
        .data_edge = PDM_RISING_EDGE  // 上升沿采样
    };
    PDM_Init(&pdm_cfg);

    // 4. 配置DMA传输
    PDM_SetupDMA(pdm_buffer, PDM_BUFFER_SIZE);
}
(2) PDM转PCM函数
// 简易PDM转PCM(需优化为高效实现)
void pdm_to_pcm(uint16_t *pdm, int16_t *pcm, uint32_t len) {
    for (int i = 0; i < len; i++) {
        int sum = 0;
        // 统计每个OSR周期内的1的数量
        for (int j = 0; j < 64; j++) {  // OSR=64
            sum += (pdm[i] >> j) & 0x1;
        }
        // 转换为有符号16位PCM(范围:-32768 ~ +32767)
        pcm[i] = (int16_t)((sum - 32) * 1024);  // 调整增益
    }
}
(3) 主程序
int main() {
    // 初始化PDM
    pdm_init();

    // 启动PDM采集
    PDM_Start();

    while (1) {
        // 等待DMA完成传输
        if (PDM_DMA_Ready()) {
            // 转换PDM到PCM
            pdm_to_pcm(pdm_buffer, pcm_buffer, PDM_BUFFER_SIZE);

            // 处理PCM数据(例如存储或传输)
            process_audio(pcm_buffer, PDM_BUFFER_SIZE);

            // 重启DMA传输
            PDM_StartDMA(pdm_buffer, PDM_BUFFER_SIZE);
        }
    }
    return 0;
}

4. 调试与验证

(1) 示波器检测
  • CLK信号:确认是否为2MHz方波。

  • DATA信号:发声时应有明显的脉冲密度变化。

(2) 数据打印

process_audio函数中打印PCM数据,观察是否随声音变化:

void process_audio(int16_t *pcm, uint32_t len) {
    for (int i = 0; i < len; i++) {
        printf("%d\n", pcm[i]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雁过留声花欲落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值