Fork me on GitHub
0%

PWM放音

原理

  1. PWM信号生成
    • PWM信号是一种数字信号,通过快速地切换信号的高低电平,并通过改变高电平持续时间(脉冲宽度)来表示不同的信号强度。
    • PWM频率(载波频率)应远高于音频信号的最高频率,以便后续处理能有效地提取音频信号。
  2. 调制音频信号
    • 数字音频信号(例如,从一个数字音频文件中读取的音频样本)用于调制PWM信号的脉宽。每个音频样本对应一个PWM周期,音频样本的值决定了该周期内高电平的持续时间。
    • 在每个PWM周期内,高电平的时间与音频样本值成正比。例如,较高的音频样本值会导致较长的高电平时间,较低的样本值会导致较短的高电平时间。
  3. 输出PWM信号
    • 通过DAC(数模转换器)或直接通过GPIO(通用输入输出)引脚输出PWM信号。输出的PWM信号在物理线路上表现为一系列快速切换的脉冲。
  4. 低通滤波
    • 由于PWM信号包含高频成分,需要通过一个低通滤波器来滤除高频部分,只保留音频信号的低频部分。低通滤波器可以是一个简单的电阻-电容(RC)滤波器或更复杂的滤波电路。
    • 滤波器的截止频率应设计为音频信号的最高频率,以确保能够有效地提取音频信号。

特点

优点

  • 实现简单,特别适合资源受限的嵌入式系统。
  • 成本低,无需复杂的DAC电路。

缺点

  • 需要高频率的PWM信号,可能会增加EMI(电磁干扰)。
  • 需要精确的低通滤波器设计,否则音质可能较差。

实际案例

以下代码的是基于Ingenic-Freertos-x1600 pwm放音demo进行说明

image

流程说明

以上图所示为例,pwm控制器频率通过AHB2或者MCLK进行分频得到一个固定时钟频率280M,基于这个频率对音频的量化。这里base_freq选择112000(可修改),音频采样率选择8K(与实际音源采样率需要一致)

参数分析

在实际的工程代码中,有以下几个参数需要进行理解

image

  • 关于Freq频率相关参数

    • SampleRate

      采样率,1s内采样点的个数。采样率8k说明1s需要输出8000个音频数据,从pwm波形来看就是1s内需要输出8000个方波,每一个方波表征一个数据点(调整占空比即调整数据大小)

    • BaseFreq

      基频(载波频率),一样是频率所以它表示1s内采样点的个数是112000个。这个频率还需要满足samplerate的数据分布,所以这个频率需要是samplerate的整数倍(这里是14倍)。理解起来就是:每一个采样点的数据重复data_mul次(8k * 14)

      (D1 D1 D1 D1 D1 D1 … D2 D2 D2 D2 D2 …)

    • PwmFreq

      PWM频率。PwmFreq与BaseFreq的关系和BaseFreq与samplerate的关系一样。也就是说BaseFreq上的每一个数据点用在PwmFreq上用pwm_full_num(2500)个方波进行表征。也就是一个数据点对应的PWM个数是2500

  • 其它参数

    • buffer_size

      代码中对于buffer_size的计算方式是:buffer_size = base_freq * unit_time / 1000 = 112000 * 50 / 1000

      BaseFreq是1s内需要准备112000个数据,除1000就表示1ms内需要准备的数据点个数。所以buffer_size大小就是 unit_time 毫秒内需要输出的采样点个数所对应的空间

    • diff

      代码中对于buffer_size的计算方式是:diff = data[0] * pwm_full_num / (0xFFFF),这里data[0]是第一个实际数据(short类型)

      1
      data / 2^{16} = diff / pwm\_full\_num

      实际数据占最大数据的百分比 = (diff)占总共pwm个数的百分比

PWM放音实现

pwm放音本身没有时钟进行同步,在音频播放的时候可能导致两个时间间隔内出现断音的情况。

这个问题出现的原因可能有:系统中进程线程调度的问题,当系统调度时间长或者系统资源紧张的时候,如果pwm缓冲区没有及时准备好数据则导致断音的出现;

对于PWM放音代码上需要采取的策略为:软件层面提供数据,硬件来保证同步关系。具体实施方案如下:整体分为两部分,PWM驱动层使用若干Descriptor串成一个环,启动DMA之后循环传输,没传输完成一个Desc来一次中断。应用层则是调用PWM驱动提供的接口写数据,而该接口在PWM 驱动中需要做到当Circle Buffer有空间的时候才能写数据否则就wait,直到dma中断到来

image

FAQ

  1. PWM音频有底噪?
    • 提高PWM频率。保证PWM的频率在20kHz以上,对于部分噪声可以滤除
    • 降低功放增益倍数。根据DataSheet调整终端电阻的阻值减小功放增益倍数,或者联系厂商取到一个最合理的值。
    • 硬件电路优化。是否需要增加增加去耦电容、是否需要进行阻抗匹配、是否喇叭质量存在问题等等

拓展资料