第04章 ES8311
约 1541 字大约 5 分钟
2026-03-23
1 组件安装
1.1. 搜索组件
ESP32组件库地址:https://components.espressif.com
搜索 "esp_codec_dev"

1.2 下载组件
在终端执行这个命令,并重新编译会自动安装
idf.py add-dependency "espressif/esp_codec_dev^1.4.0"2. 代码实现
int_es8311.h
#ifndef __INT_ES8311_H__
#define __INT_ES8311_H__
// 包含I2C驱动头文件
#include "driver/i2c.h"
// 包含I2S驱动头文件
#include "driver/i2s_std.h"
#include "driver/i2s_tdm.h"
#include "soc/soc_caps.h"
// 包含设备头文件
#include "esp_codec_dev.h"
#include "esp_codec_dev_defaults.h"
#include "unity.h"
// 定义ES8311使用的I2C引脚
#define ES8311_I2C_SDA_PIN GPIO_NUM_0
#define ES8311_I2C_SCL_PIN GPIO_NUM_1
// 定义ES8311使用的I2S引脚
#define ES8311_I2S_MCK_PIN GPIO_NUM_3
#define ES8311_I2S_BCK_PIN GPIO_NUM_2
#define ES8311_I2S_DATA_WS_PIN GPIO_NUM_5
#define ES8311_I2S_DATA_OUT_PIN GPIO_NUM_6
#define ES8311_I2S_DATA_IN_PIN GPIO_NUM_4
// 定义功放控制引脚
#define ES8311_PA_GPIO GPIO_NUM_46
/**
* @brief 初始化ES8311音频编解码器
*
*/
void int_es8311_init(void);
/**
* @brief 反初始化ES8311音频编解码器
*
*/
void int_es8311_deinit(void);
/**
* @brief 从麦克风读取音频数据
*
* @param buffer 将读取到音频存入该缓冲区
* @param len 要读取的长度
*/
void int_es8311_read_mic(uint8_t *buffer, int len);
/**
* @brief 写入音频数据到扬声器
*
* @param buffer 要写入的数据缓冲区
* @param len 要写入的长度
*/
void int_es8311_write_speaker(uint8_t *buffer, int len);
/**
* @brief 设置音量
*
* @param volume 音量值,范围根据实际设备而定,通常为0-100
*/
void int_es8311_set_volume(int volume);
/**
* @brief 设置静音状态
*
* @param mute true表示静音,false表示取消静音
*/
void int_es8311_set_mute(bool mute);
#endif /* __INT_ES8311_H__ */int_es8311.c
#include "int_es8311.h"
// 定义麦克风句柄作为I2S的接收句柄
i2s_chan_handle_t mic_handler = NULL;
// 定义扬声器句柄作为I2S的发送句柄
i2s_chan_handle_t speaker_handler = NULL;
// 定义设备实例
esp_codec_dev_handle_t codec_dev = NULL;
// 静态函数: 初始化 I2C
static void int_es8311_i2c_init(void)
{
// 配置 I2C 参数
i2c_config_t i2c_cfg = {
.mode = I2C_MODE_MASTER, // 设置为主机模式
.sda_pullup_en = GPIO_PULLUP_ENABLE, // 启用 SDA 线上拉电阻
.scl_pullup_en = GPIO_PULLUP_ENABLE, // 启用 SCL 线上拉电阻
.master.clk_speed = 100000, // 设置 I2C 时钟频率为 100kHz
};
// 设置 I2C 引脚
i2c_cfg.sda_io_num = ES8311_I2C_SDA_PIN;
i2c_cfg.scl_io_num = ES8311_I2C_SCL_PIN;
// 应用 I2C 参数配置
i2c_param_config(I2C_NUM_0, &i2c_cfg);
// 安装 I2C 驱动程序
i2c_driver_install(I2C_NUM_0, i2c_cfg.mode, 0, 0, 0);
}
// 静态函数: 反初始化 I2C
static void int_es8311_i2c_deinit(void)
{
i2c_driver_delete(I2C_NUM_0);
}
// 静态函数:初始化 I2S
// - STD 模式:标准 I2S/PCM 格式,支持 2 通道
// - TDM 模式:时分复用模式,支持更多通道(需要硬件支持)
static void int_es8311_i2s_init(void)
{
// 配置 I2S 通道基本参数, 设置I2S 端口号和主机模式
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
// 配置标准 I2S 模式参数(用于双通道立体声)
i2s_std_config_t std_cfg = {
// 时钟配置:默认 16kHz 采样率
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
// 槽位配置:16 位数据,立体声模式,使用 Philips 标准格式
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_STEREO),
// GPIO 引脚配置
.gpio_cfg = {
.mclk = ES8311_I2S_MCK_PIN, // 主时钟引脚(MCLK)
.bclk = ES8311_I2S_BCK_PIN, // 位时钟引脚(BCLK/SCLK)
.ws = ES8311_I2S_DATA_WS_PIN, // 字选择引脚(WS/LRCK)
.dout = ES8311_I2S_DATA_OUT_PIN, // 数据输出引脚(DOUT,用于播放)
.din = ES8311_I2S_DATA_IN_PIN, // 数据输入引脚(DIN,用于录音)
},
};
// 创建 I2S 通道(同时创建发送和接收通道)
i2s_new_channel(&chan_cfg, &speaker_handler, &mic_handler);
// 使用标准 I2S 模式初始化发送通道
i2s_channel_init_std_mode(speaker_handler, &std_cfg);
// 使用标准 I2S 模式初始化接收通道
i2s_channel_init_std_mode(mic_handler, &std_cfg);
// 使能发送通道 在全双工模式下,发送通道作为主时钟源,需要先使能
i2s_channel_enable(speaker_handler);
// 使能接收通道
i2s_channel_enable(mic_handler);
}
// 静态函数:反初始化 I2S
static void int_es8311_i2s_deinit(void)
{
// 关闭通道
i2s_channel_disable(speaker_handler);
i2s_channel_disable(mic_handler);
// 删除通道
i2s_del_channel(speaker_handler);
i2s_del_channel(mic_handler);
}
// 静态函数:初始化 ES8311 本身以及相关设备
static void int_es8311_dev_init(void)
{
// 1. 创建数据接口
// 1.1 设置参数
audio_codec_i2s_cfg_t i2s_cfg = {
.rx_handle = mic_handler,
.tx_handle = speaker_handler,
};
// 1.2 创建接口
const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);
// 2. 创建控制接口
// 2.1 设置参数,指定 I2C 从设备地址
audio_codec_i2c_cfg_t i2c_cfg = {.addr = ES8311_CODEC_DEFAULT_ADDR};
// 2.2 创建接口
const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);
// 3. 创建 GPIO 接口
const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();
// 4. 定义配置参数
es8311_codec_cfg_t es8311_cfg = {
.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,
.ctrl_if = out_ctrl_if,
.gpio_if = gpio_if,
.pa_pin = ES8311_PA_GPIO,
.use_mclk = true,
};
// 5. 使用配置参数创建 codec 接口
const audio_codec_if_t *out_codec_if = es8311_codec_new(&es8311_cfg);
// 6. 创建设备对象
// 6.1 设置参数
esp_codec_dev_cfg_t dev_cfg = {
.codec_if = out_codec_if, // es8311_codec_new 获取到的接口实现
.data_if = data_if, // audio_codec_new_i2s_data 获取到的数据接口实现
.dev_type = ESP_CODEC_DEV_TYPE_IN_OUT // 设备同时支持录制和播放
};
// 6.2 创建对象
codec_dev = esp_codec_dev_new(&dev_cfg);
// 7. 设置音量和增益
// 7.1 设置音量
esp_codec_dev_set_out_vol(codec_dev, 60);
// 7.2 设置麦克风增益
esp_codec_dev_set_in_gain(codec_dev, 20.0);
// 8. 启动设备对象
esp_codec_dev_sample_info_t fs = {
.sample_rate = 16000, // 采样率使用16kHz
.channel = 1, // 单声道
.bits_per_sample = 16, // 位深
};
esp_codec_dev_open(codec_dev, &fs);
}
// 静态函数:反初始化 ES8311 本身以及相关设备
static void int_es8311_dev_deinit(void)
{
if (codec_dev != NULL)
{
esp_codec_dev_close(codec_dev);
}
}
/**
* @brief 初始化ES8311音频编解码器
*
*/
void int_es8311_init(void)
{
// 1. 初始化 I2C
int_es8311_i2c_init();
// 2. 初始化 I2S
int_es8311_i2s_init();
// 3. 初始化 ES8311 本身以及相关设备
int_es8311_dev_init();
}
/**
* @brief 反初始化ES8311音频编解码器
*
*/
void int_es8311_deinit(void)
{
// 1. 反初始化 ES8311 本身以及相关设备
int_es8311_dev_deinit();
// 2. 反初始化 I2S
int_es8311_i2s_deinit();
// 3. 反初始化 I2C
int_es8311_i2c_deinit();
}
/**
* @brief 从麦克风读取音频数据(获取录音)
*
* @param buffer 将读取到音频存入该缓冲区
* @param len 要读取的长度
*/
void int_es8311_read_mic(uint8_t *buffer, int len)
{
if (codec_dev != NULL)
{
esp_codec_dev_read(codec_dev, buffer, len);
}
}
/**
* @brief 写入音频数据到扬声器(播放声音)
*
* @param buffer 要写入的数据缓冲区
* @param len 要写入的长度
*/
void int_es8311_write_speaker(uint8_t *buffer, int len)
{
if (codec_dev != NULL)
{
esp_codec_dev_write(codec_dev, buffer, len);
}
}
/**
* @brief 设置音量
*
* @param volume 音量值,范围根据实际设备而定,通常为0-100
*/
void int_es8311_set_volume(int volume)
{
if (codec_dev != NULL)
{
esp_codec_dev_set_out_vol(codec_dev, volume);
}
}
/**
* @brief 设置静音状态
*
* @param mute true表示静音,false表示取消静音
*/
void int_es8311_set_mute(bool mute)
{
if (codec_dev != NULL)
{
esp_codec_dev_set_out_mute(codec_dev, mute);
}
}main.c 测试
#include <stdio.h>
#include "esp_task.h"
#include "com_debug.h"
#include "int_es8311.h"
void app_main(void)
{
MY_LOGI("ES8311 Test:");
// 初始化 ES8311 音频编解码器
int_es8311_init();
// 设置音量
int_es8311_set_volume(60);
// 定义数组作为音频数据的缓冲区
uint8_t audio_buffer[512];
while (1)
{
// 读取麦克风数据
int_es8311_read_mic(audio_buffer, 512);
// 将读取到的数据写入扬声器
int_es8311_write_speaker(audio_buffer, 512);
// 延时10ms
vTaskDelay(10);
}
}3. 使用旧版本I2C的组件

3.1 修改方式1

3.2 修改方式2
检查menuconfig配置
idf.py menuconfig选择

选择

选择

