3649| 1
|
[ESP8266/ESP32] FireBeetle 直接放音(PWM篇) |
本帖最后由 zoologist 于 2021-4-9 08:52 编辑 前面介绍了FireBeetle通过 DAC 来播放音频,除此之外,还可以使用 PWM 方式来播放音频。 关于 PWM动力老男孩在“Arduino系列教程之 – PWM的秘密(上)”【参考1】有介绍,对于我们来说,能用到的就是下面这一段: PWM是用占空比不同的方波,来模拟“模拟输出”的一种方式。靠,这个太拗口了,简而言之就是电脑只会输出0和1,那么想输出0.5怎么办呢?于是输出01010101….,平均之后的效果就是0.5了。早这么说就了然了嘛。 ![]() 比如,当前最高电压是5V,如果输出50%的PWM信号,可以当作 2.5V 的信号输出。 对于 ESP32来说,有对 PWM的直接支持【参考2】。 Arduino core for the ESP32 并没有一般Arduino 中用来输出 PWM 的analogWrite(pin, value) 方法,取而代之的 ESP32 有一个 LEDC ,设计是用来控制 LED 。 ESP32 的 LEDC 总共有16个路通道(0 ~ 15),分为高低速两组,高速通道(0 ~ 7)由80MHz时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。 对于我们来说,用到的函数有下面3个: ledcSetup(uint8_t channel, double freq, uint8_tresolution_bits) 分别设定使用的通道(Channel),PWM 的频率, PWM 的分辨率。比如,我们设定1Hz 的频率,然后分辨率为4Bit,那么就可以设置从 0 到15,一共16个PWM值。可以看出,分辨率越高,可以细分出更多的 PWM值。 ledcWrite(uint8_t channel, uint32_t duty) 对通道设定当前的占空比(duty) ledcAttachPin(uint8_t pin, uint8_t channel) 将 LEDC 通道绑定到指定IO 口上 这样,我们就得到了一个和之前 DAC 很像的代码:
测试结果表示和 DAC 的音质无差别。 前面提到了,PWM支持更高的分辨率,因此,我们可以尝试播放16Bits的音频。最简单的想法,直接将频率设定为8000Hz,然后PWM信号分辨率为16位。但是实际测试下来这样无法工作,经过研究,频率和分辨率之间有一定的限制关系【参考3】。在 8000Hz 下能够达到最高分辨率是13bits。最终实验表明使用12Bits 分辨率8000Hz 可以接收,再高噪音会较大。此外,16bits的 WAV 和 8Bits 的还有一个很大的区别在于:前者是有符号数值,后者是无符号数值。比如:0x8001实际上表示的是 -1。因此代码中取出数值后需要加上 0x8000 再做处理。另外,因为 16Bits 相对于 8Bits 数据量是直接翻倍了,导致无法在 Flash 中放下全部文件,为此,16Bits音频数据只是部分歌曲。
参考: The maximum PWM frequency with the currently used ledc dutyresolution of 10 bits in PWM module is 78.125KHz. The duty resolution can be lowered down to 1 bit in whichcase the maximum frequency is 40 MHz, but only the duty of 50% is available. For duty resolution of 8 buts, the maximal frequency is312.5 kHz. The available duty levels are (2^bit_num)-1, where bit_num canbe 1-15. The maximal frequency is 80000000 / 2^bit_num In my MicroPython implementation, I'm currently working onenabling user selectable and/or automatic duty resolution and higher maxumumfrequencies. 4.手册上有描述 ![]() |
© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed