提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本系列将以0基础新手视角,完整演示ESP32+ inmp441+max98357 的全流程及代码实现。建议搭配Arduino IDE 2.0+和ESP32-S3开发板使用。
(二)本文为ESP32-S3连接 inmp441+max98357
一、前期准备
1.1 硬件配置
需准备ESP32-S3开发板 和 inmp441全向麦克风模块 和 max98357
1.2 软件环境配置
安装Arduino IDE 2.0.2
安装 ESP32 库(工具→开发板管理→搜索ESP32→安装)
二、接线
ESP32-S3 | inmp441 |
---|---|
3.3v | VDD |
GND | GND |
6 | WS |
4 | SD |
7 | SCK |
ESP32-S3 | max98357 |
---|---|
3.3v | VDD |
GND | GND |
16 | MAX98357_LRC |
17 | MAX98357_BCLK |
18 | MAX98357_DIN |
喇叭 | max98357 |
---|---|
+ | + |
负 | 负 |
三、核心代码
3.1 (录音机)代码
注意
11号引脚置底,开始录音(录音时间要低于5s,不然超出内存),置高则停止录音
10号引脚置底,开始播放录音,置底则停止播放
若是播放无声音,说明录音过长,需要重新录音
9号引脚,接LED灯显示用,可不接
调节音量,修改代码中的 5 倍数太高,声音会是失真+噪
for (int i = 0; i < count; i++) {
int32_t amplified = sample[i] * 5; // 乘以3倍音量
if (amplified > 32767) amplified = 32767;
if (amplified < -32768) amplified = -32768;
tempBuffer[i] = (int16_t)amplified;
}
代码(录音机):
#include <Arduino.h>
#include <driver/i2s.h>
#include <hal/i2s_types.h>
#define INMP441_WS 6
#define INMP441_SCK 7
#define INMP441_SD 4
#define MAX98357_LRC 16
#define MAX98357_BCLK 17
#define MAX98357_DIN 18
#define SAMPLE_RATE 16000
#define SAMPLE_SECONDS 5 // 最多录音秒数(内存限制)
#define BUFFER_SIZE (SAMPLE_RATE * SAMPLE_SECONDS)
const int recordPin = 11;
const int playPin = 10;
const int LEDPin = 9;
i2s_config_t inmp441_i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 128
};
const i2s_pin_config_t inmp441_gpio_config = {
.bck_io_num = INMP441_SCK,
.ws_io_num = INMP441_WS,
.data_out_num = -1,
.data_in_num = INMP441_SD
};
i2s_config_t max98357_i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 128
};
const i2s_pin_config_t max98357_gpio_config = {
.bck_io_num = MAX98357_BCLK,
.ws_io_num = MAX98357_LRC,
.data_out_num = MAX98357_DIN,
.data_in_num = -1
};
uint8_t *recordBuffer = nullptr;
size_t recordedBytes = 0;
void setup() {
Serial.begin(115200);
pinMode(recordPin, INPUT_PULLUP); // D11
pinMode(playPin, INPUT); // D10
pinMode(LEDPin, OUTPUT); // D9
// 初始化麦克风 I2S
i2s_driver_install(I2S_NUM_0, &inmp441_i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &inmp441_gpio_config);
// 初始化扬声器 I2S
i2s_driver_install(I2S_NUM_1, &max98357_i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_1, &max98357_gpio_config);
// 分配录音缓冲区
recordBuffer = (uint8_t *)malloc(BUFFER_SIZE * sizeof(uint16_t));
if (!recordBuffer) {
Serial.println("Failed to allocate memory!");
while (1);
}
}
void loop() {
// 录音逻辑
if (digitalRead(recordPin) == LOW) {
digitalWrite(LEDPin,HIGH);
Serial.println("开始录音...");
// 清空缓冲区,防止旧数据残留
memset(recordBuffer, 0, BUFFER_SIZE * sizeof(uint16_t));
recordedBytes = 0;
size_t bytesRead;
while (digitalRead(recordPin) == LOW && recordedBytes < BUFFER_SIZE * sizeof(uint16_t)) {
i2s_read(I2S_NUM_0, recordBuffer + recordedBytes, 512, &bytesRead, portMAX_DELAY);
recordedBytes += bytesRead;
}
Serial.println("录音结束");
}
digitalWrite(LEDPin,LOW);
// 播放逻辑
if (digitalRead(playPin) == LOW && recordedBytes > 0) {
Serial.println("开始播放...");
size_t bytesWritten = 0;
while (bytesWritten < recordedBytes) {
size_t writeSize;
size_t chunkSize = 512;
if (recordedBytes - bytesWritten < chunkSize) {
chunkSize = recordedBytes - bytesWritten;
}
// 放大音量:把采样数据乘上一个倍数
int16_t* sample = (int16_t*)(recordBuffer + bytesWritten);
int16_t tempBuffer[256]; // 临时缓冲区,用来保存放大后的数据
int count = chunkSize / 2;
for (int i = 0; i < count; i++) {
int32_t amplified = sample[i] * 5; // 乘以3倍音量
if (amplified > 32767) amplified = 32767;
if (amplified < -32768) amplified = -32768;
tempBuffer[i] = (int16_t)amplified;
}
i2s_write(I2S_NUM_1, tempBuffer, chunkSize, &writeSize, portMAX_DELAY);
bytesWritten += writeSize;
}
Serial.println("播放完成");
delay(1000); // 防止重复触发
}
}
3.2 (麦克风喇叭)代码
注意
调节音量,修改代码中的 5 倍数太高,声音会是失真+噪
for (int i = 0; i < count; i++) {
int32_t amplified = sample[i] * 5; // 乘以3倍音量
if (amplified > 32767) amplified = 32767;
if (amplified < -32768) amplified = -32768;
tempBuffer[i] = (int16_t)amplified;
}
#include <Arduino.h>
#include <driver/i2s.h>
#include <hal/i2s_types.h>
#define INMP441_WS 6
#define INMP441_SCK 7
#define INMP441_SD 4
#define MAX98357_LRC 16
#define MAX98357_BCLK 17
#define MAX98357_DIN 18
// #define SAMPLE_RATE 44100
#define SAMPLE_RATE 16000
const int inputPin = 5;
i2s_config_t inmp441_i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8, // buffer 的数量
.dma_buf_len = 128 // buffer的大小,单位是i2s_bits_per_sample_t 采样位数,越小播放需要越及时时延越小,否则相反
};
const i2s_pin_config_t inmp441_gpio_config = {
.bck_io_num = INMP441_SCK,
.ws_io_num = INMP441_WS,
.data_out_num = -1,
.data_in_num = INMP441_SD
};
i2s_config_t max98357_i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 128
};
const i2s_pin_config_t max98357_gpio_config = {
.bck_io_num = MAX98357_BCLK,
.ws_io_num = MAX98357_LRC,
.data_out_num = MAX98357_DIN,
.data_in_num = -1
};
void setup()
{
pinMode(inputPin, INPUT);
i2s_driver_install(I2S_NUM_0, &inmp441_i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &inmp441_gpio_config);
i2s_driver_install(I2S_NUM_1, &max98357_i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_1, &max98357_gpio_config);
}
void loop()
{
size_t bytes_read;
uint16_t data[256];
esp_err_t result = i2s_read(I2S_NUM_0, &data, sizeof(data), &bytes_read, portMAX_DELAY);
size_t bytes_write;
int val = digitalRead(inputPin);
if (val == HIGH)
{
result = i2s_write(I2S_NUM_1, &data, sizeof(data), &bytes_write, portMAX_DELAY);
}
}
四、(录音机)最终效果
11号引脚置底,开始录音(录音时间要低于5s,不然超出内存),置高则停止录音
10号引脚置底,开始播放录音,置底则停止播放
若是播放无声音,说明录音过长,需要重新录音
9号引脚,接LED灯显示用,可不接
五、(麦克风喇叭)最终效果
对着麦克风,讲话。
喇叭会对应出声。
总结
本文是为验证《基于Arduino的ESP32-S3+inmp441+max98357(录音机/麦克风喇叭)的驱动》