ESP32 + MAX98357A+喇叭+SSD OLED1306

模块引脚接线说明
ESP32GPIO22→ MAX98357A DIN
ESP32GPIO26→ MAX98357A BCLK
ESP32GPIO25→ MAX98357A LRC(或 WS)
ESP325V→ MAX98357A VIN(推荐使用 5V)
ESP32GND→ MAX98357A GND
MAX98357AOUT+→ 喇叭正极
MAX98357AOUT−→ 喇叭负极
你的项目/

├── data/

│ └── music.mp3

├── src/

│ └── main.cpp

├── platformio.ini

#include <Arduino.h>
#include <SPIFFS.h>
#include <Audio.h>
#include <WiFi.h>

// WiFi 信息
const char* ssid = "Y0ur_SSID";
const char* password = "Y0ur_pass";

// I2S 引脚定义
#define I2S_DOUT  22
#define I2S_BCLK  26
#define I2S_LRC   25

Audio audio;

void setup() {
  Serial.begin(115200);
  delay(1000);

  // 连接 WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // 初始化 SPIFFS(可选,如果不再用可以注释)
  // if (!SPIFFS.begin(true)) {
  //   Serial.println("SPIFFS 挂载失败!");
  //   return;
  // }

  // 初始化音频(使用 I2S 输出)
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(10); // 0~21

  // 播放公网 MP3
  audio.connecttohost("http://www.taotao01.fun/music.mp3");
}

void loop() {
  audio.loop(); // 必须放 loop 中不断调用
}

pio run --target uploadfs #上传文件

进阶版V2

元件ESP32 引脚说明
MAX98357A DOUT(DIN)GPIO 22音频数据(I2S DATA)
MAX98357A BCLKGPIO 26I2S 时钟
MAX98357A LRC(WS)GPIO 25I2S 左右声道同步
OLED SDAGPIO 21I2C 数据
OLED SCLGPIO 22I2C 时钟(共用没问题)
按钮 1GPIO 34播放/暂停(输入,仅支持输入)
按钮 2GPIO 35下一首(输入,仅支持输入)
点击查看代码
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Audio.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// ==== 配置 ==== //
const char* ssid = "Y0ur_SSID";
const char* password = "Y0ur_pass";
const char* music_api = "http://www.expamle.com/get_music_list.php";

// OLED 设置
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// 按钮引脚
#define BUTTON_PLAY 34
#define BUTTON_NEXT 35

// I2S 引脚
#define I2S_DOUT 25
#define I2S_BCLK 26
#define I2S_LRC  27

Audio audio;
bool isPlaying = false;

// 音乐信息结构体
struct MusicItem {
  String url;
  String title;
};

// ========== 获取音乐 JSON ==========
MusicItem fetchMusicURL() {
  MusicItem result;
  HTTPClient http;
  http.begin(music_api);
  int httpCode = http.GET();

  if (httpCode == 200) {
    String payload = http.getString();
    http.end();

    StaticJsonDocument<1024> doc;
    DeserializationError error = deserializeJson(doc, payload);
    if (!error && doc.is<JsonArray>()) {
      JsonObject obj = doc[0];
      result.url = obj["url"].as<String>();
      result.title = obj["title"].as<String>();
    }
  } else {
    http.end();
  }

  return result;
}

// ========== OLED 显示函数 ==========
void showStatus(const String& line1, const String& line2 = "") {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 10);
  display.println(line1);
  display.println(line2);
  display.display();
}

// ========== 播放下一首 ==========
void playNext() {
  showStatus("Loading...");
  MusicItem item = fetchMusicURL();
  if (item.url != "") {
    showStatus("Playing", item.title);
    audio.connecttohost(item.url.c_str());
    isPlaying = true;
  } else {
    showStatus("Failed to load");
  }
}

// ========== 初始化 ==========
void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_PLAY, INPUT_PULLUP);
  pinMode(BUTTON_NEXT, INPUT_PULLUP);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 init failed");
    while (true);
  }
  showStatus("WiFi Connected", WiFi.localIP().toString());

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(10);

  playNext();
}

// ========== 主循环 ==========
unsigned long lastPlayNextTime = 0;

void loop() {
  static bool lastPlayState = HIGH;
  static bool lastNextState = HIGH;

  // 播放/暂停
  bool currentPlay = digitalRead(BUTTON_PLAY);
  if (currentPlay == LOW && lastPlayState == HIGH) {
    if (isPlaying) {
      audio.stopSong();
      showStatus("Paused");
      isPlaying = false;
    } else {
      playNext();
    }
  }
  lastPlayState = currentPlay;

  // 下一首
  bool currentNext = digitalRead(BUTTON_NEXT);
  if (currentNext == LOW && lastNextState == HIGH) {
    playNext();
  }
  lastNextState = currentNext;

  // ✅ 播放完成 -> 自动下一首(加延时防抖)
  if (!audio.isRunning() && isPlaying) {
    unsigned long now = millis();
    if (now - lastPlayNextTime > 3000) {  // 至少间隔3秒
      playNext();
      lastPlayNextTime = now;
    }
  }

  audio.loop();
  delay(50);
}
来听听响~ 如有雷同 ,请告知
posted @ 2025-08-11 21:54  huh&uh  阅读(137)  评论(0)    收藏  举报