ESP32基于Arduino框架,SD卡+MAX98357模块+MP3播放器

原创作者的制作教程讲解以及源码:

35 ESP32之简单的完整功能SD卡MP3播放器的制作讲解(ESP32-audioI2S库介绍)- 基于Arduino

链接:https://pan.baidu.com/s/1IxmHo1M8TLo13XMwSbZrfQ?pwd=2hgy

提取码:2hgy

OLED播放效果演示:

由于还没有购买MAX98357,不知道音质怎么样。

MAX98357 I2S 音频放大器模块 MAX98357 I2S 音频放大器模块 无滤波D类放大器资料:

https://pan.baidu.com/s/1Bn6zpobgbs93CyBALzPxqg

提取码: j9y9

SD卡接线说明

✨使用VSPI接口接线

// #define SD_CS 5

// #define SPI_MOSI 23

// #define SPI_MISO 19

// #define SPI_SCK 18

I2C OLED屏幕接线

原创代码定义的是4,15需要注意,可以根据自己的需求自行修改

OLED SCL-----> 21

OLED SDA ----> 22

所需库

编译信息参考:

使用 2.0.0 版本的库 Wire 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\libraries\Wire

使用 2.0.0 版本的库 SPI 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\libraries\SPI

使用 2.33.15 版本的库 U8g2 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\U8g2

使用 2.2.0 版本的库 SdFat 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\SdFat

使用 2.2.1 版本的库 RBD_Button 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\RBD_Button

使用 1.4.2 版本的库 RBD_Timer 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\RBD_Timer

使用 2.0.0 版本的库 ESP32-audioI2S 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\ESP32-audioI2S

使用 2.0.0 版本的库 WiFi 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\libraries\WiFi

使用 2.0.0 版本的库 WiFiClientSecure 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\libraries\WiFiClientSecure

"C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\gcc8_4_0-esp-2021r2-patch3/bin/xtensa-esp32-elf-size" -A "d:\\arduino\\MyHexDir/real_player.ino.elf"

项目使用了 1084461 字节,占用了 (82%) 程序存储空间。最大为 1310720 字节。

全局变量使用了42272字节,(12%)的动态内存,余留285408字节局部变量。最大为327680字节。

U8g2库 RBD_Button库 RBD_Timer 库

SdFat库 esp32-audioi2s需要自己导入到Arduino IDE库当中

esp32-audioi2s: https://github.com/schreibfaul1/esp32-audioi2s

⛳注意事项

需要按照原作者那样修改ESP32-audioI2S库代码。

Audio.h头文件 源文件Audio.cpp

⚡程序烧录后,需要初始化SD卡成功后,屏幕才能显,如果没有找到SD或识别到SD卡,则串口会打印error。(具体看代码)

程序代码

#include

#include

#include

#include //点击这里会自动打开管理库页面: http://librarymanager/All#U8g2

#include "SdFat.h"//点击这里会自动打开管理库页面: http://librarymanager/All#SdFat

#include

#include //点击这里会自动打开管理库页面: http://librarymanager/All#RBD_Button

#include "Audio.h"

#include "FileEnumerator.h"

using namespace std;

//#define SCL 17

//#define SDA 16

// #define SD_CS 5

// #define SPI_MOSI 23

// #define SPI_MISO 19

// #define SPI_SCK 18

#define V_SUB_PIN 32 // v-

#define V_ADD_PIN 33 // v+

#define STOP_PIN 16 //stop

#define PREV_PIN 17 //prev

#define NEXT_PIN 15 //next

#define I2S_DOUT 25

#define I2S_BCLK 26

#define I2S_LRC 27

//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // 没有重置显示的所有板

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // 1.3寸,默认引脚SCL:22,SDA:21

//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/SCL, /* data=*/SDA); // 1.3寸,指定引脚

RBD::Button vsub_button(V_SUB_PIN, INPUT_PULLUP);

RBD::Button vadd_button(V_ADD_PIN, INPUT_PULLUP);

RBD::Button stop_button(STOP_PIN, INPUT_PULLUP);

RBD::Button prev_button(PREV_PIN, INPUT_PULLUP);

RBD::Button next_button(NEXT_PIN, INPUT_PULLUP);

int volume = 10; //音量

Audio audio;

FileEnumerator fe;

char buf[128];

int utf8CutLen(const String &src, int utf8Len) {

int utf8LenCnt = 0;

int srcIdx = 0;

int srcLen = src.length();

int cutLen = 0;

unsigned char tmp;

while (utf8LenCnt < utf8Len && srcIdx < srcLen) {

tmp = (unsigned char)src[srcIdx];

if (tmp >= 252)

cutLen = 6;

else if (tmp >= 248)

cutLen = 5;

else if (tmp >= 240)

cutLen = 4;

else if (tmp >= 224)

cutLen = 3;

else if (tmp >= 192)

cutLen = 2;

else if (tmp >= 65 && tmp <=90)

cutLen = 1;

else

cutLen = 1;

srcIdx += cutLen;

++utf8LenCnt;

}

return srcIdx;

}

void UpdateOLED()

{

u8g2.clearBuffer();

u8g2.setFont(u8g2_font_wqy14_t_gb2312b); //换成中文字体

string str = "音量: " + std::to_string(volume);

if(audio.isRunning())

str+=" 播放中...";

else

str+=" 未播放...";

u8g2.drawUTF8(0, 15, str.c_str());

String tmp = fe.CurrentFileName();

int len = tmp.length();

int len1 = utf8CutLen(tmp, 10);

if(len>len1)

{

u8g2.drawUTF8(0, 40, tmp.substring(0, len1).c_str());

u8g2.drawUTF8(0, 55, tmp.substring(len1).c_str());

}

else

u8g2.drawUTF8(0, 40, fe.CurrentFileName());

u8g2.sendBuffer();

}

void PlayPrev()

{

auto filename = fe.Prev();

if(!filename)

return;

audio.stopSong();

delay(3);

audio.connecttoFS(SD, filename);

Serial.print("play: ");

Serial.println(filename);

}

void PlayNext()

{

auto filename = fe.Next();

if(!filename)

return;

audio.stopSong();

delay(3);

audio.connecttoFS(SD, filename);

Serial.print("play: ");

Serial.println(filename);

}

void setup() {

Serial.begin(115200);

delay(3000);

if(!SD.begin(SdSpiConfig(5, DEDICATED_SPI, 18000000)))

//if(!SD.begin(5, 18000000))

{

Serial.println("error");

return;

}

FsFile dir;

FsFile file;

fe.Init();

file.remove("/index.idx");

if(!file.open("/index.idx", O_RDWR|O_CREAT))

{

Serial.println("crate file error");

return;

}

// Open root directory

if (!dir.open("/")){

Serial.println("dir.open failed");

return;

}

while (file.openNext(&dir, O_RDONLY)) {

memset(buf, 0, 128);

file.getName(buf, 128);

fe.Add(buf);

file.close();

}

dir.close();

fe.Flush();

Wire.begin(SDA, SCL);

u8g2.setBusClock(800000); //设置时钟

u8g2.begin(); //初始化

u8g2.enableUTF8Print(); //允许UTF8

vsub_button.setDebounceTimeout(20);

vadd_button.setDebounceTimeout(20);

stop_button.setDebounceTimeout(20);

prev_button.setDebounceTimeout(20);

next_button.setDebounceTimeout(20);

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);

audio.setVolume(10); // 0...21

PlayNext();

UpdateOLED();

}

void audio_eof_mp3(const char *info)

{

PlayNext();

UpdateOLED();

}

void audio_id3data(const char *info){

UpdateOLED();

}

void loop() {

if(vsub_button.onPressed())

{

// V-

volume --;

if(volume < 0)

volume = 0;

audio.setVolume(volume);

UpdateOLED();

}

if(vadd_button.onPressed())

{

// V+

volume ++;

if(volume > 21)

volume = 21;

audio.setVolume(volume);

UpdateOLED();

}

if(stop_button.onPressed())

{

//暂停,播放

audio.pauseResume();

UpdateOLED();

}

if(prev_button.onPressed())

{

PlayPrev();

UpdateOLED();

}

if(next_button.onPressed())

{

PlayNext();

UpdateOLED();

}

audio.loop();

}

工程代码

链接:https://pan.baidu.com/s/1XX_88x4WfDoW2DHvmN3gYA

提取码:k72b

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: