ESP32+micropython+MP3-TF-16P播放mp3音乐

444 阅读4分钟

QQ图片20240911181923.png

小白一枚

MP3-TF-16P相关视频教程: MP3-TF-16P语音播放模块使用分享     基于MicroPython和ESP32的物联网开发-第18课 播放MP3音频

MP3-TF-16P手册及相关资料

接线

MP3-TF-16P   排线    ESP32
vcc ---      红色 --- 3v3
rx ---       紫色 --- gpio25
tx ---       棕色 --- gpio26
GND ---      黑色 --- GND
BUSY ---     白色 --- io27

命令

0x7e + 0xff + 0x06 + 命令 + 0x00 + para1 + para2 + hight_byte + low_byte + 0xef

0x7e:起始位,每条命令均以0x7e开头
0xff:版本号
0x06:命令长度,起始位、hight_byte、low_byte和0xef不计在内
命令:各种功能的命令,如播放命令0x03。更多命令请查阅MP3-TF-16P使用说明书:通讯指令
0x00:命令反馈,是否需要反馈信息,1反馈,0不反馈,默认不反馈
para1:查询的数据高字节
para2:查询的数据低字节
hight_byte:校验和的高字节
low_byte:校验和的低字节
0xef:结束位

如播放播放第一首的命令7E FF 06 03 00 00 01 FE F7 EF 就写成:
b'~\xff\x06\x03\x00\x00\x01\xfe\xf7\xef'

计算校验和

去掉起始位和结束位,将中间的6个字节进行累加,最后取反码。

image.png

from machine import UART, Pin
from utime import sleep_ms

# 硬件初始化部分
uart = UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=25, rx=26)

# 协议常量定义
_START_BYTE = 0x7E
_VER = 0xFF
_END_BYTE = 0xEF
# 系统参数
_FEEDBACK = 0x00
_CMD_LEN  = 0x06

# 命令类型枚举
class CMD:
    SET_VOLUME  = 0x06
    SET_EFFECT  = 0x07
    PLAY        = 0x03
    PLAY_SRC    = 0x0F
    QUERY_STATUS= 0x42
    PAUSE       = 0x0E
    RESUME      = 0x0D
    STOP        = 0x16
    RANDOM      = 0x18
    QUERY_TF    = 0x48
    QUERY_DIR   = 0x4E

def send_command(cmd: int, param1: int, param2: int, delay: int = 500):
    """发送控制命令通用函数
    Args:
        cmd: 命令码
        param1: 第一参数
        param2: 第二参数
        delay: 发送后等待时间(ms)
    """
    checksum = 0 - (_VER + _CMD_LEN + cmd + _FEEDBACK + param1 + param2)
    command = bytes([
        _START_BYTE,
        _VER,
        _CMD_LEN,
        cmd,
        _FEEDBACK,
        param1,
        param2,
        (checksum >> 8) & 0xFF,  # 高位校验字节
        checksum & 0xFF,         # 低位校验字节
        _END_BYTE
    ])
    uart.write(command)
    sleep_ms(delay)  # 根据设备响应需求调整延时

def query_play_status() -> int:
    """查询播放状态
    Returns:
        0: 播放完毕 7E FF 06 42 00 00 00 xx xx EF
        1: 正在播放 7E FF 06 42 00 00 01 xx xx EF
        2: 播放过程中被暂停 7E FF 06 42 00 00 02 xx xx EF
        8: 当前在睡眠状态 7E FF 06 42 00 00 08 xx xx EF
    """
    sleep_ms(500)
    send_command(CMD.QUERY_STATUS, 0, 0)
    sleep_ms(100)
    data = uart.readline()
    status = data[6]
    return status

def query_tracks(folder: int = 0) -> int:
    """查询曲目总数
    Args:
        folder: 文件夹内的总曲目,默认查询TF卡总文件数
        
    Returns:
        int: 曲目总数
    """
    if folder != 0:
        send_command(CMD.QUERY_DIR, 0, folder)
    else:
        send_command(CMD.QUERY_TF, 0, 0)
    sleep_ms(500)
    send_command(CMD.QUERY_STATUS, 0, 0)
    data = uart.readline()
    result = data[6]
    return result

def play(*args: int):
    """播放音乐
    args:
        只传一个参数时播放TF卡音乐;传两个参数时播放文件夹内的音乐
    """
    if len(args) == 0:
        return
    elif len(args) == 1:
        send_command(CMD.PLAY, 0, args[0])
    else:
        para1, para2 = args
        send_command(CMD.PLAY_SRC, para1, para2)


if __name__ == '__main__':
    send_command(CMD.SET_VOLUME, 0, 22) # 设置音量
    send_command(CMD.SET_EFFECT, 0, 1) # 设置EQ
    play(1) # 播放TF卡第一首
    sleep_ms(10000)
    print(query_play_status()) # 查询播放状态
    print(query_tracks(1)) # 查询01文件夹的曲目总数
    print(query_tracks(2)) # 查询02文件夹的曲目总数
    print(query_tracks(3)) # 查询02文件夹的曲目总数
    send_command(CMD.RESUME, 0, 0) # 恢复播放,查询会中断播放
    sleep_ms(10000)
    send_command(CMD.PAUSE, 0, 0) # 暂停播放
    play(2, 2) # 播放02文件夹第2首