ESP32-IDF使用I2S驱动MAX98375--解析WAV文件

一. 简介

本篇文章将介绍如何使用ESP32S3通过I2S发送WAV音频数据,驱动MAX98375A进行音频的播放。是EVE_V2项目开发的一部分工作。

二. MAX98375A介绍

芯片特性如下,可以在芯片手册上找到。

  • 单电源工作(2.5V至5.5V)
  • 3.2W输出功率:4Ω,5V
  • 2.4mA静态电流
  • 92%效率(RL = 8Ω,POUT = 1W)
  • 25µVRMS输出噪声(AV = 15dB)
  • 1kHz时,0.015% THD+N
  • 无需MCLK
  • 8kHz至96kHz采样速率
  • 支持左声道、右声道以及(左声道/2 + 右声道/2)输出

外围驱动电路图图如下,用与I2S通讯的IO口有三个: BCLK,LRCLK,DIN。用于控制芯片的引脚有两个:

GAIN: 控制增益值,一般直接拉高即可,有特殊增益的话,可以查看下图,或者Database的 Table8。

SD_MODE: 根据电平值控制左右声道模式,其内部串联了一个100K的电阻,在外部调整上拉电阻的阻值调整模式,拉低可以使芯片Shutdown不工作
ESP32-IDF使用I2S驱动MAX98375--解析WAV文件_第1张图片
ESP32-IDF使用I2S驱动MAX98375--解析WAV文件_第2张图片

三. I2S协议

信号线:

  1. BCLK: 位时钟,SD信号的发送与采集和BCLK进行对齐,时钟速率 = 采样率 * 量化位宽 * 通道数
  2. SD: 数据输入输出信号,麦克风对应输出DOUT,扬声器对应DIN,MSB模式输出。
  3. WS: 左右声道选择信号LRCLK,WS=0 ,表示当前的数据为左声道,WS=1,表示当前数据为右声道。
  4. MCLK: 主设置,可以不管。

针对MAX98375A的I2S时序图如下,LRCLK用于表示当前的数据的是左声道还是右声道数数据。

ESP32-IDF使用I2S驱动MAX98375--解析WAV文件_第3张图片

当然其中还有许多细节,这些就不需要我们管了,用FPGA做的话,就需要你非常清楚啦。

四. ESP32IDF I2S驱动

根据上面I2S的一点点介绍,可以知道I2S主要涉及到三个参数:采样率 * 量化位宽 * 通道数,所以配置的时候,也是配置这三个参数

    i2s_config_t i2s_config = {
            .mode = I2S_MODE_MASTER | I2S_MODE_TX,              // 使用主模式并设置为发送数据
            .sample_rate = 44100,                               // 设置采样率为44100Hz
            .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,       // 设置每个采样点的位数为16位
            .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,       // 只使用右声道
            .communication_format = I2S_COMM_FORMAT_STAND_I2S,  // I2S通信格式
            .dma_buf_count = 8,                                 // 设置DMA缓冲区数量为8
            .dma_buf_len = 1024,                                // 每个DMA缓冲区的长度为1024字节
            .intr_alloc_flags = ESP_INTR_FLAG_EDGE,             // 分配中断标志
    };
 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

配置好,I2S的参数后,就要配置引脚了,方法如下

    i2s_pin_config_t pin_config = {
            .bck_io_num = MAX98375_BCLK_IO1,            // BCLK引脚号
            .ws_io_num = MAX98375_LRCLK_IO1,             // LRCK引脚号
            .data_out_num = MAX98375_DOUT_IO1, // DATA引脚号
            .data_in_num = -1,           // DATA_IN引脚号
    };
  i2s_set_pin(I2S_NUM_0, &pin_config);

这样I2S就配置好了,然后就调用下面的函数向I2S中发送数据就可以了。

i2s_write(I2S_NUM_0,buf,len,&sizes,1000);

五. WAV 文件解析

WAV文件的格式 和之前解析过的图片文件bmp类似,整个文件可以分为两大部分: 文件头 和 音频数据部分。我们需要从文件头中获取到I2S所涉及到的三个参数: :采样率 * 量化位宽 * 通道数,以及音频数据

整个文件格式如下,文件头一共包括44个字节。从图中可以看到每一个部分的大小和偏移地址,以及存储模式是大端存储 还是 小端存储。

ESP32-IDF使用I2S驱动MAX98375--解析WAV文件_第4张图片

  1. NumChannels: 通道数,1为单通道,左通道或者右通道都可,2为双通道,即立体声。
  2. SampleRate: 采样率
  3. BitsPerSample: 音频数据
  4. data : 音频数据

在每次读取WAV文件的时候,需要根据提取到的信息更新I2S配置,即可。

在ESP32_IDF的例程中,给出了WAV文件格式的结构体

ESP32-IDF使用I2S驱动MAX98375--解析WAV文件_第5张图片

在每次发送完数据后,一定要stop I2S,负责喇叭会有异响,而且可能会发热严重。

    FILE* fp = TFCard_Open("/sdcard/3.wav","rb");

    struct WAV_File_Head wave_file_head;
    uint8_t wav_hd[44];
    TFCard_Read(fp,wav_hd,44);

    wave_file_head.chunkId          = *(uint32_t *)(wav_hd + 0);
    wave_file_head.chunkSize        = *(uint32_t *)(wav_hd + 4);
    wave_file_head.format           = *(uint32_t *)(wav_hd + 8);
    wave_file_head.subchunk1Id      = *(uint32_t *)(wav_hd + 12);
    wave_file_head.subchunk1Size    = *(uint32_t *)(wav_hd + 16);
    wave_file_head.audioFormate     = *(uint16_t *)(wav_hd + 20);
    wave_file_head.numChannels      = *(uint16_t *)(wav_hd + 22);
    wave_file_head.sampleRate       = *(uint32_t *)(wav_hd + 24);
    wave_file_head.byteRatem        = *(uint32_t *)(wav_hd + 28);
    wave_file_head.blockAlign       = *(uint16_t *)(wav_hd + 32);
    wave_file_head.bitsPerSanple    = *(uint32_t *)(wav_hd + 34);
    wave_file_head.subchunk2Id      = *(uint32_t *)(wav_hd + 36);
    wave_file_head.subchunk2Size    = *(uint32_t *)(wav_hd + 40);
    i2s_start(I2S_NUM_0);
     while( 1 ){
        uint8_t data[1024];
        uint32_t tt = TFCard_Read(fp,data,1024);
        if( tt < 1024){
            return;
        }
        MAX98375_I2S_Send_Buf(data,1024);
        vTaskDelay(5);
    }
    vTaskDelay(pdMS_TO_TICKS(200)); //延时200ms
    i2s_zero_dma_buffer(I2S_NUM_0);
    i2s_stop(I2S_NUM_0);

六. 小结

本篇文章 介绍了 如何通过解析WAV文件,然后通过I2S 发送给MAX98375A进行音乐播放,介绍的比较简单,只介绍了比较重要的部分,以使用的目的介绍,没有过多的去说明细节;当用上了之后,再根据兴趣去研究相关的细节比较好。需要完整代码的可以在gzh ↓ 进行私聊

欢迎关注 微信公众号 FPGA之旅,qq群 649098696

你可能感兴趣的:(单片机,fpga开发,esp32,i2s,max98375a)