十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ESP32 低成本音频方案全解析:esp-iot-solution 中的 PWM Audio、DAC Audio 与 ADC Mic 组件

ESP32 低成本音频方案全解析:esp-iot-solution 中的 PWM Audio、DAC Audio 与 ADC Mic 组件 ESP32 低成本音频方案全解析esp-iot-solution 中的 PWM Audio、DAC Audio 与 ADC Mic 组件【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本指南基于 esp-iot-solution 仓库的音频文档体系docs/en/audio系统讲解三类免外部 Codec 芯片的音频解决方案基于 LEDC 外设的 PWM 输出、基于 I2S 内置 DAC 的输出以及基于 ADC 连续采样模式的麦克风输入。读完本文你将掌握这三类方案的核心原理、关键配置参数、API 调用流程、硬件参考设计要点以及如何在成本敏感的产品中依据音质与采样率要求做出正确选型。一、音频组件概览与选型依据在 esp-iot-solution 仓库中音频相关组件位于 components/audio 目录下包含三个彼此独立的组件组件目录方向核心外设适用场景pwm_audiocomponents/audio/pwm_audio音频输出LEDCPWM成本敏感、音质要求低的播放场景dac_audiocomponents/audio/dac_audio音频输出I2S 内置 DACESP32 芯片上的无外部 Codec 播放adc_miccomponents/audio/adc_mic音频输入ADCcontinuous 模式低成本模拟麦克风采集三者的共同点是无需外部音频 Codec 芯片这也是它们区别于传统 I2S Codec 方案的核心价值。官方文档分别位于 docs/en/audio/pwm_audio.rst、docs/en/audio/dac_audio.rst 与 docs/en/audio/adc_mic.rst并提供了对应中文版本 docs/zh_CN/audio/pwm_audio.rst 等。二、PWM Audio用 LEDC 外设播放音频2.1 工作原理与整体结构PWM 音频功能使用 ESP32 系列芯片的内部 LEDC 外设产生 PWM 信号来播放音频无需外部的音频 Codec 芯片主要用于对音质要求不高而对成本敏感的应用。其数据通路如下整个处理流程分为三步数据重编码首先对写入的数据进行编码调整以满足 PWM 的输入要求包括数据的移位shift和偏移offset处理送入环形缓冲区通过一个 Ring Buffer 将编码后的数据发送到 Timer Group 的 ISR中断服务例程函数定时驱动 LEDCTimer Group 按照预先设定的采样率从 Ring Buffer 读出数据并写入 LEDC 输出 PWM 波形。注意由于输出的是 PWM 信号数字方波必须对输出进行低通滤波后才能得到可听的音频波形。2.2 特性清单允许使用任意具有输出能力的 GPIO作为音频输出管脚支持8 ~ 10 位的 PWM 分辨率组件 README 中描述为 8 ~ 16 位见 components/audio/pwm_audio/README.md实际可用范围取决于所选芯片的 LEDC 能力支持立体声左右双通道支持8 ~ 48 KHz采样率。2.3 PWM 频率计算分辨率与频率的权衡输出 PWM 的频率不支持直接配置需要通过配置 PWM 分辨率位数来计算公式如下f_pwm f_APB_CLK / 2^res_bits - ((f_APB_CLK / 2^res_bits) MOD 1000)其中f_APB_CLK为 80 MHzres_bits为 PWM 分辨率位数。当分辨率为LEDC_TIMER_10_BIT10 位时PWM 频率约为78 KHz。更高的 PWM 频率和分辨率能更好地还原音频信号但从公式可以看出增大 PWM 频率意味着分辨率降低提高分辨率意味着频率减小。以 80 MHz APB 时钟为例分辨率位数 res_bits理论 PWM 频率约8 位312 KHz10 位78 KHz12 位19.5 KHz因此请根据实际应用场景调整这两个参数在频率与分辨率之间取得良好平衡——例如选择 8 位分辨率换取更高 PWM 频率或选择 10 位分辨率换取更好的幅度还原精度。2.4 配置结构体pwm_audio_config_t配置结构体定义于 components/audio/pwm_audio/include/pwm_audio.h字段含义如下字段含义取值范围/说明gpio_num_left左声道 LEDC 输出 GPIO任意可输出 GPIOgpio_num_right右声道 LEDC 输出 GPIO任意可输出 GPIOledc_channel_left左声道对应 LEDC 通道0 ~ 7ledc_channel_right右声道对应 LEDC 通道0 ~ 7ledc_timer_sel通道的定时器源0 ~ 3duty_resolutionLEDC PWM 分辨率位数如LEDC_TIMER_10_BITringbuf_len环形缓冲区大小字节如1024 * 8注意在 ESP-IDF 5.0 之前该结构体还包含tg_num定时器组号 0~1与timer_num定时器号 0~1IDF 5.0 起改用gptimer驱动这两个字段不再需要头文件中通过ESP_IDF_VERSION条件编译区分。2.5 应用示例官方文档给出了完整的调用流程见 docs/en/audio/pwm_audio.rstpwm_audio_config_t pac; pac.duty_resolution LEDC_TIMER_10_BIT; pac.gpio_num_left LEFT_CHANNEL_GPIO; pac.ledc_channel_left LEDC_CHANNEL_0; pac.gpio_num_right RIGHT_CHANNEL_GPIO; pac.ledc_channel_right LEDC_CHANNEL_1; pac.ledc_timer_sel LEDC_TIMER_0; pac.tg_num TIMER_GROUP_0; pac.timer_num TIMER_0; pac.ringbuf_len 1024 * 8; pwm_audio_init(pac); /** Initialize pwm audio */ pwm_audio_set_param(48000, 8, 2); /** Set sample rate, bits and channel number */ pwm_audio_start(); /** Start to run */ while(1) { // Prepare audio data, such as decode mp3/wav file /** Write data to play */ pwm_audio_write(audio_data, length, written, 1000 / portTICK_PERIOD_MS); }2.6 API 参考完整函数清单从 pwm_audio.h 可以确认以下公开 API函数功能返回说明pwm_audio_init(cfg)初始化并配置 PWM 音频ESP_OK参数错误返回ESP_ERR_INVALID_ARG重复配置返回ESP_ERR_INVALID_STATE内存不足返回ESP_ERR_NO_MEMpwm_audio_deinit()反初始化 LEDC、定时器组并释放输出 GPIO未初始化返回ESP_FAILpwm_audio_start()开始播放未初始化或已在运行返回ESP_ERR_INVALID_STATEpwm_audio_stop()停止播放注意仅停止定时器PWM 仍会保持输出如需停止 PWM 输出需调用pwm_audio_deinitpwm_audio_write(inbuf, len, bytes_written, ticks_to_wait)写入数据播放超时时bytes_written会小于传入的lenticks_to_wait可传portMAX_DELAY表示无限等待pwm_audio_set_param(rate, bits, ch)设置采样率、位宽与声道数启动后不可修改参数需先pwm_audio_stoppwm_audio_set_sample_rate(rate)仅设置采样率采样率如 8000、44100pwm_audio_set_volume(volume)设置音量范围-16 ~ 160 为原始输出小于 0 为衰减-16 即静音大于 0 为放大16 即双倍输出。音量过小会产生严重失真pwm_audio_get_volume(volume)获取当前音量volume为输出参数pwm_audio_get_param(rate, bits, ch)获取当前参数不关心的参数可传NULLpwm_audio_get_status(status)获取状态PWM_AUDIO_STATUS_UN_INIT/IDLE/BUSY组件还定义了声道枚举PWM_AUDIO_CH_MONO单声道与PWM_AUDIO_CH_STEREO双声道状态枚举PWM_AUDIO_STATUS_UN_INIT / IDLE / BUSY。2.7 测试验证与依赖组件自带测试程序 components/audio/pwm_audio/test_apps/main/pwm_audio_test.c内置了多种测试波形数据单声道 8/16 位、双声道 8/16 位见 wave_1ch_16bits.c 等并在 test_apps 下附带sine_wave_test.png正弦波输出截图可用于验证 PWM 播放效果。该组件通过 idf_component.yml 声明依赖可通过组件管理器直接引入。三、DAC AudioI2S 内置 DAC 播放3.1 方案原理ESP32 拥有两个独立的 DAC 通道可以直接使用I2S 通过 DMA播放音频。dac_audio组件在 ESP-IDF 的基础上简化了 API并对相关数据进行了重新编码以支持更多类型的采样位宽。重要限制该方案仅支持 ESP32 芯片因为 ESP32-S2 等芯片的 I2S 外设没有内置 DAC见 dac_audio.h 中的注释说明。3.2 配置结构体dac_audio_config_t字段含义说明i2s_numI2S 端口号I2S_NUM_0、I2S_NUM_1sample_rateI2S 采样率如 16000、48000bits_per_sampleI2S 每样本位数i2s_bits_per_sample_t类型dac_modeDAC 模式I2S_DAC_CHANNEL_LEFT_EN/RIGHT_EN/BOTH_EN等dma_buf_countDMA 缓冲区数量如 8dma_buf_len每个 DMA 缓冲区的长度如 1024max_data_size单次最大写入数据量如16 * 10243.3 测试用例中的完整用法components/audio/dac_audio/test/dac_audio_test.c 提供了可运行的最小示例初始化时配置 I2S 端口、采样率、位宽、DAC 模式与 DMA 参数随后调用dac_audio_set_param(48000, 8, 2)重设参数并dac_audio_start()启动最后循环dac_audio_write()写入数据dac_audio_config_t dac_cfg; dac_cfg.i2s_num I2S_NUM_0; dac_cfg.sample_rate 16000; dac_cfg.bits_per_sample 16; dac_cfg.dac_mode I2S_DAC_CHANNEL_LEFT_EN; dac_cfg.dma_buf_count 8; dac_cfg.dma_buf_len 1024; dac_cfg.max_data_size 16 * 1024; dac_audio_init(dac_cfg); dac_audio_set_param(48000, 8, 2); dac_audio_start(); // 循环 dac_audio_write(...) 播放数据该测试用例用正弦/余弦函数生成了带相位差的双声道波形f 48000 / 240 200Hz直接验证了双通道输出效果测试目录下同样准备了单/双声道、8/16 位的波形数据文件wave_1ch_16bits.c 等。3.4 API 参考dac_audio提供的 API 与 PWM 音频高度对称方便迁移dac_audio_init(cfg)/dac_audio_deinit()dac_audio_start()/dac_audio_stop()dac_audio_set_param(rate, bits, ch)设置采样率、位宽与声道数dac_audio_set_volume(volume)音量范围 -16 ~ 16注意大于 0 的音量可能引起变量溢出与失真通常应使用小于或等于 0 的音量dac_audio_write(inbuf, len, bytes_written, ticks_to_wait)写数据播放四、ADC Mic用 ADC 采集模拟麦克风4.1 方案原理与特性使用 ADC 采集模拟麦克风数据无需外部音频 Codec 芯片适用于对采样精度要求不太高且成本敏感的应用。在代码结构上该组件采用esp_codec_dev的工程模式基于 audio_codec_data_if.h 中的audio_codec_data_if_t数据接口可以无缝接入基于 esp_codec_dev 的音频框架。特性支持多路 ADC 音频采样通过adc_channel_list指定多个通道支持最大12 位ADC 采样分辨率。注意多路采样支持的最大分辨率取决于 ADC 最大采样率除以采样通道数。例如 ESP32-S3 的 ADC 最大采样率为 83.3K双通道采样时单通道分辨率上限约为 41.6K。4.2 硬件参考电路与设计要点参考电路见下图电路设计要点详见 docs/en/audio/adc_mic.rst放大拓扑可以选择跨阻放大器TIA或同相/反相放大电路对 MIC 输入信号进行放大。大多数情况下跨阻放大器可以获得更佳的信噪比偏置电路示例中 R29 用于为 MIC 添加直流偏置通用运放LMV321作为运算放大器R26 与 C19 构成反馈电路使运放工作在跨阻放大模式阻容值需根据 MIC 灵敏度调整R31 与 R30 用于设定中位电压以避免交越失真R27 与 R32 提供直流偏置避免 ADC 采集时失真偏置要求ADC 端的中点偏置是必须的如 Vref/2以避免 ADC 采集失真。默认情况下ESP32-C3 的 Vref 约为 0.9V电源要求MIC 供电最好使用LDO稳压避免电源波动影响 ADC 采样若不使用外部 LDO应在电源侧单独做 RC 滤波示例中 R28 与 C23 用于滤波MIC 与运放推荐独立供电MIC 选型推荐选择灵敏度大于 -46 dB的 MIC避免放大后信噪比过低并根据 MIC 灵敏度调整放大倍数。4.3 配置结构体audio_codec_adc_cfg_t定义于 adc_mic.h字段含义说明handleADC 连续模式驱动句柄为NULL时组件内部自动创建否则复用外部传入的句柄max_store_buf_size驱动可存储转换结果的最大长度字节宏默认1024 * 2conv_frame_size转换帧大小字节应为SOC_ADC_DIGI_DATA_BYTES_PER_CONV的整数倍宏默认 1024unit_idADC 单元ADC_UNIT_1等adc_channel_listADC 通道列表宏中通过数组字面量传入adc_channel_num通道数量单声道宏为 1atten衰减档位应匹配实际输入范围0 dB 衰减波纹最小sample_rate_hzADC 采样率如 16000组件提供了两个便捷初始化宏DEFAULT_AUDIO_CODEC_ADC_MONO_CFG(channel, sample)单声道配置DEFAULT_AUDIO_CODEC_ADC_STEREO_CFG(channel_l, channel_r, sample)立体声配置注意当前实现中adc_channel_num仍为 1实际立体声采集请按需求调整。4.4 外部配置 ADC Continuous 模式可以在组件外部先初始化好 ADC 连续模式再将adc_continuous_handle_t传入组件复用adc_continuous_handle_t handle; adc_continuous_handle_cfg_t adc_config { .max_store_buf_size adc_cfg-max_store_buf_size, .conv_frame_size adc_cfg-conv_frame_size, .flags.flush_pool true, }; adc_continuous_new_handle(adc_config, handle);4.5 与 ADC Oneshot 模式共用如果 ADC oneshot 与 ADC continuous使用不同的 ADC Unit则不会有冲突如果使用相同的 ADC Unit请先调用esp_codec_dev_close()关闭adc_mic再调用adc_oneshot_read。adc_continuous_start(handle); adc_continuous_read(); adc_continuous_stop(); adc_oneshot_read();4.6 完整示例代码文档提供了基于 esp_codec_dev 接口的完整采集流程见 docs/en/audio/adc_mic.rstaudio_codec_adc_cfg_t cfg DEFAULT_AUDIO_CODEC_ADC_MONO_CFG(ADC_CHANNEL_0, 16000); const audio_codec_data_if_t *adc_if audio_codec_new_adc_data(cfg); esp_codec_dev_cfg_t codec_dev_cfg { .dev_type ESP_CODEC_DEV_TYPE_IN, .data_if adc_if, }; esp_codec_dev_handle_t dev esp_codec_dev_new(codec_dev_cfg); esp_codec_dev_sample_info_t fs { .sample_rate 16000, .channel 1, .bits_per_sample 16, }; esp_codec_dev_open(dev, fs); uint16_t *audio_buffer malloc(16000 * sizeof(uint16_t)); assert(audio_buffer); while (1) { int ret esp_codec_dev_read(dev, audio_buffer, sizeof(uint16_t) * 16000); ESP_LOGI(TAG, esp_codec_dev_read ret: %d\n, ret); }4.7 Kconfig 配置项组件通过 Kconfig 提供以下运行时配置配置项默认值范围说明ADC_MIC_APPLY_GAIN30 ~ 4对 ADC 数据施加增益0 无增益1~4 分别左移 1~4 位2x / 4x / 8x / 16x 增益ADC_MIC_OFFSET随增益联动-与APPLY_GAIN联动的直流偏移补偿2048 ~ 32760ADC_MIC_TASK_PRIORITY10 ~ 15ADC 麦克风工作任务优先级ADC_MIC_TASK_STACK_SIZE30722048 ~ 8192工作任务栈大小ADC_MIC_TASK_CORE-1-1 ~ 1任务绑核-1 表示不绑定4.8 已知问题与集成提示组件 READMEcomponents/audio/adc_mic/README.md明确指出IDF 版本低于 5.2 时内部 ring buffer 在写满时不会自动清除旧数据需及时清理旧数据或手动刷新缓冲区从esp_codec_dev v1.5.6 起已原生支持 ADC Micmenuconfig 中启用通常不再需要单独引入本组件组件依赖可通过组件管理器添加idf.py add-dependency espressif/adc_mic*。五、三方案对比与选型建议维度PWM AudioDAC AudioADC Mic方向输出输出输入核心外设LEDC TimerIDF 5.0 后为 gptimerI2S 内置 DACADC continuous芯片限制ESP32 系列通用仅 ESP32ESP32 系列通用采样率8 ~ 48 KHz由 I2S 与 DAC 决定受 ADC 最大采样率限制S3 为 83.3K / 通道数位宽/分辨率8 ~ 10 位README 称可达 16 位支持多种采样位宽经重编码最大 12 位声道单/立体声单/立体声单/多路外围电路需低通滤波直接输出需前置放大/偏置电路音质定位较低中等中低采样率受限选型建议需要最便宜的播放方案、音质要求低 → 选pwm_audio任意 GPIO 即可输出注意必须外接低通滤波器使用ESP32 芯片且希望免 Codec 获得更好音质 → 选dac_audio直接利用内置 DAC DMA需要低成本采集模拟麦克风 → 选adc_mic配合esp_codec_dev框架使用注意 ADC 采样率上限与硬件偏置电路。三个组件的源码、测试与文档均位于当前仓库中components/audio、docs/en/audio其中pwm_audio和dac_audio都提供了完整的测试波形与可运行测试用例adc_mic提供了完整的测试应用test_apps可作为快速上手的参考实现。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表