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

2023-09-22 14:31:43

一. 简介

本篇文章将介绍如何使用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不工作
请添加图片描述
请添加图片描述

三. I2S协议

信号线:

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

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

请添加图片描述

当然其中还有许多细节,这些就不需要我们管了,用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个字节。从图中可以看到每一个部分的大小和偏移地址,以及存储模式是大端存储 还是 小端存储。

请添加图片描述

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

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

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

请添加图片描述

在每次发送完数据后,一定要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

更多推荐

Grom 如何解决 SQL 注入问题

什么是SQL注入SQL注入是一种常见的数据库攻击手段,SQL注入漏洞也是网络世界中最普遍的漏洞之一。SQL注入就是恶意用户通过在表单中填写包含SQL关键字的数据来使数据库执行非常规代码的过程。这个问题的来源就是,SQL数据库的操作是通过SQL命令执行的,无论是执行代码还是数据项都必须卸载SQL语句中,这就导致如果我们在

【操作系统笔记十二】Linux常用基础命令

Linux常用快捷键Tab命令或路径等的补全键,特别常用的快捷键Ctrl+insert复制命令行内容(常用可提高效率)Shift+insert粘贴命令行内容(常用可提高效率)Ctrl+C中断当前任务(退出)Ctrl+Z暂停当前任务Ctrl+I清除屏幕所有的内容Ctrl+A光标迅速回到行首Ctrl+E光标迅速回到行尾Ct

红 黑 树

文章目录一、红黑树的概念二、红黑树的实现1.红黑树的存储结构2.红黑树的插入一、红黑树的概念在AVL树中删除一个结点,旋转可能要持续到根结点,此时效率较低红黑树也是一种二叉搜索树,通过在每个结点中增加一个位置来存储红色或黑色,并对结点的着色进行限制,使得该二叉搜索树的最长路径不超过最短路径的两倍,即红黑树是一颗近似平衡

【postgresql】ERROR: column “xxxx.id“ must appear in the GROUP BY

org.postgresql.util.PSQLException:ERROR:column"xxx.id"mustappearintheGROUPBYclauseorbeusedinanaggregatefunction错误:列“XXXX.id”必须出现在GROUPBY子句中或在聚合函数中使用在mysql中是正常使用

【八大经典排序算法】冒泡排序

【八大经典排序算法】冒泡排序一、概述二、思路解读三、代码实现四、优化一、概述冒泡排序由于其简单和易于理解,使其成为初学者学习排序算法的首选,也是初学者接触到的第一个排序算法。其原理是通过重复交换相邻的元素来将最大的元素逐步“冒泡”到最后。冒泡排序由美国计算机科学家冯·诺伊曼(JohnvonNeumann)于1945年提

使用singularity本地部署wandb

1.背景:wandbself-host(本地部署)官网只支持docker,而不支持singularity,但是现在部分高校或者企业在集群上完全使用singularity替代docker(原因:docker可以挂载任意目录,而容器内是root权限,导致容器外对文件设置的权限,在容器内完全是无用的,因为root用户可以访问

内存泄漏,内存溢出,抽象类和接口,netstat、ping、ifconfig的区别

持续学习是我们必备的技能之一,保持与时俱进,保持行业的敏感度,关注行业发展趋势,了解新技术,加强自己的认知,积极的应对变化内存泄漏memoryleak是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出内存泄漏可以分为四类1、常发性内存泄漏,发生内存泄漏的代

微信小程序部分知识点总结

简单描述下微信小程序的目录结构微信小程序的目录结构如下:app.js。微信小程序的主逻辑文件,用于描述小程序的基本逻辑和程序入口。app.json。微信小程序的公共设置文件,用于描述小程序的全局配置项,如页面路径、窗口样式等。app.wxss。微信小程序的公共样式表文件,用于描述小程序的全局样式,如字体、颜色等。pag

Java基于基于微信小程序的快递柜管理系统

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌文章目录第一章:简介第二章、***\*开发环境:\******后端:****前端:****数据库:**第三章系统设计3.3系统功能设计3.3.1用户注册

APP开发者如何运用积分墙广告,提升APP应用下载和用户留存?

“积分墙”移动广告通过在应用内展示各种积分任务,鼓励用户完成任务以获得积分奖励,从而增加应用的曝光度和下载量。一、什么是积分墙?积分墙是一种第三方移动广告平台。开发者可以在这类平台上发布任务(如下载安装App、注册、填表等),用户完成相应任务就可以获得积分或现金奖励,达到指定额度可以提现。二、积分墙包含哪几部分?(1)

springBoot整合minio

<minio.version>8.3.4</minio.version><!--其它&&数据源加密--><org.bouncycastle.bcprov-jdk15on.version>1.70</org.bouncycastle.bcprov-jdk15on.version><dependencies><depend

热文推荐