这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享开发笔记,赚取电动螺丝刀】使用ESP32S3调试I2S音频模块MAX983

共9条 1/1 1 跳转至

【分享开发笔记,赚取电动螺丝刀】使用ESP32S3调试I2S音频模块MAX98357

专家
2025-05-13 19:35:35   被打赏 22 分(兑奖)     打赏

学习I2S有一段时间了,基本上理解了I2S的工作方式和逻辑波形构成。和预想的不一样,I2SI2C的其区别还是挺大的,最明显的就是模式上,I2S有左对齐、飞利浦、右对齐以及PCM四种方式,方式不一样,输出数据波形就会有不同。按照这个理解,意味着对接的I2S音频转换芯片,一样会有不同的工作方式,而不是像音频放大器那样,简单对接音频输入就行。

为了进一步学习I2S音频转换芯片从输入到输出的变化,买了一个MAX98357模块。MAX98357模块已经有专门的帖子介绍了。前面说过了I2S数据有不同的工作方式,但MAX98357模块提供的几个引脚中,看不到能适配工作模式的引脚,也没有看类似于TLV320AIC23B那样的控制接口配置工作参数,看资料说MAX98357是固定工作于PCM编码模式的。但是如果不用飞利浦标准模式设置ESP32S3的I2S的话,输出的声音不正常。

为了快速体验I2S的整个工作效果,没继续花时间去了解MAX98357,而是直接上手试验。I2S的主体使用ESP32S3模块,在Arduino环境下进行编程测试。

ESP32S3模块:

 

图片1.png


 MAX98357模块:

图片2.png

 

 

两个模块的连接方式:

ESP32S3模块                MAX98357模块

------------------------------------------------

3.3V                         Vin

GND                        GND

GPIO6                      DIN

GPIO8                      LRC

GPIO9                      BCLK

3.3V                         SD

                                GAIN(控制增益,悬空即可)

------------------------------------------------

需要在Arduino下的开发板管理器中安装ESP32S3,我选择的是ESP32S3 Dev Module

程序代码如下:


#include <Arduino.h>
#include "driver/i2s.h"
 
// I2S 配置参数
#define I2S_BCLK 9
#define I2S_LRC  8
#define I2S_DOUT 6
 
// 音频参数
#define SAMPLE_RATE 44100
#define SAMPLE_BITS 16
#define BUFFER_SIZE 1024
 
// 生成正弦波测试音频
void generateSineWave(int16_t* buffer, size_t samples, float frequency, float volume) {
  static float phase = 0.0;
  float phaseIncrement = 2 * PI * frequency / SAMPLE_RATE;
  
  for (size_t i = 0; i < samples; i++) {
    buffer[i] = volume * sin(phase) * 32767; // 16位有符号整数范围
    //Serial.println(buffer[i]);
    phase += phaseIncrement;
    if (phase >= 2 * PI) phase -= 2 * PI;
  }
}
 
 
void setup() {
  Serial.begin(921600);
  
  // 配置 I2S
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = (i2s_bits_per_sample_t)SAMPLE_BITS,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    //.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4,
    .dma_buf_len = BUFFER_SIZE,
    .use_apll = false
  };
 
  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_BCLK,
    .ws_io_num = I2S_LRC,
    .data_out_num = I2S_DOUT,
    .data_in_num = I2S_PIN_NO_CHANGE
  };
 
  // 初始化 I2S
  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
}
 
void loop() {
  int16_t audioBuffer[BUFFER_SIZE];
 
  // 生成 1000Hz 正弦波
  generateSineWave(audioBuffer, BUFFER_SIZE, 1000, 0.1);  
 
  // 通过 I2S 发送音频数据
  size_t bytesWritten;
  i2s_write(I2S_NUM_0, audioBuffer, sizeof(audioBuffer), &bytesWritten, portMAX_DELAY);
}

 

出于快速验证的目的,测试中没有使用播放MP3WAV等音频文件的方式,而是使用程序生成正弦波的采样点(利用sin函数),用来模拟正弦波。频率设置为1KHz,保证用扬声器能听到这个频率的声音。

 

整个实验装置及实验效果:

 

装置.png

使用的是8欧姆的喇叭,没想到声音还是挺大的,

演示视频文件:demo.zip

通过Arduino串口绘图仪获取的采样数据绘制的波形:

 

图片3.png


是正弦波。

注意:如果想从串口得到这个波形,需要在generateSineWave函数中去掉Serial.println(buffer[i]);的注释,但这样做会让声音变得不连续。

改变正弦波的频率和音量比例参数(generateSineWave函数中的第三个和第四个参数),喇叭声音会发生相应的变化。

 MAX98357的输出端(喇叭)获得的波形(由示波器测得):

 图片4.png


黄色的是喇叭两端得到的波形(有正弦波的模样,但不全,嘿嘿)。

按照我的理解,以44.1KHz采样1KHz的正弦波,采样周期为1/44.1KHz = 0.022mS1KHz的周期为1mS,也就是说,一个完整的1KHz的正弦波按照44.1KHz采样,只能采集到44个点。而1024个数据可以获得大约23个完整的正弦波形。不知道是不是因为loop循环处理的太快导致示波器测不到那么多正弦波。后面继续调整程序,以期获得理想的效果。或者播放音频文件试试,这样更容易判断处理是否正常。



专家
2025-05-13 22:22:53     打赏
2楼

感谢分享


专家
2025-05-13 22:24:31     打赏
3楼

感谢分享


专家
2025-05-13 22:28:36     打赏
4楼

感谢分享


高工
2025-05-17 21:46:12     打赏
5楼

I2S其实还不止这些,还有一种I2S叫I2STDM,从波形上来说,I2S属于特殊的TDM格式。


高工
2025-05-17 21:51:34     打赏
6楼

MAX98357属于D类功放,输出端要加滤波电路才能量到信号波形的,不然就全是脉宽调制的载波信号


高工
2025-05-19 12:59:02     打赏
7楼

期待后续使用音频文件来输出的效果。


专家
2025-05-19 17:28:06     打赏
8楼

很仔细的探索方式,学习了。


工程师
2025-05-21 10:35:49     打赏
9楼

蛮不错的I2S学习记录, 可以尝试使用INMP441 作为输入然后使用MAX98375作为输出


共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]