单片机
返回首页

单片机与BY8301-16P语音模块串口通信详解:实现指定音频播放功能

2025-09-26 来源:cnblogs

一、串口语音模块

这里我们使用的具体型号是:CH32V307VCT6开发板和BY8301-16P 语音模块。

以下是BY8301-16P语音模块的一些主要特点:

  • 高品质音频播放: 支持MP3和WAV两种主流音频格式解码,提供高品质的声音输出。具有24位DAC输出,支持90dB的动态范围和85dB的信噪比(SNR)。

  • 内置存储介质: 内置SPI-FLASH作为存储介质,通常有4MB(32Mbit)或更大的容量,最大可支持16M Byte容量的SPI FLASH(例如GD25Q128)。

  • 方便的音频更新: 配有Micro USB接口,无需上位机软件,可以直接通过数据线连接电脑(支持XP和WIN7系统)自由更换FLASH中的音频内容,操作简便。

  • 集成功放: 模块内置3W功放,可以直接驱动3W/4Ω或2W/8Ω的喇叭,方便使用,无需额外添加功放电路。

  • 多种控制方式:

  • IO口触发播放: 支持21段语音一对一触发播放,通过3个IO口(A、B、C)配合3.3K电阻接地或不接,可以选择8种硬件触发模式,应用广泛。

  • UART异步串口控制: 内置标准UART异步串口接口(3.3V TTL电平),可以通过串口命令进行播放、暂停、上下曲、音量加减、选曲播放、广告插播等操作。这使得它可以通过单片机、电脑串口等进行灵活控制。

  • 内置记忆功能: 支持音量、曲目、EQ(均衡器)掉电记忆功能。

  • 小巧封装: 采用标准的2.54mm间距DIP16封装,体积小巧,方便集成到各种产品中。

  • 宽电压供电: 工作电压范围为3.6V-5V,推荐值4.2V。

  • 模块引脚原理图:

    引脚编号引脚名称功能描述
    1SPK2喇叭输出2(直接连接喇叭的一个引脚,与SPK1组成差分输出)
    2SPK1喇叭输出1(直接连接喇叭的另一个引脚,与SPK2组成差分输出)
    3DACL左声道音频数据输入(通常用于连接外部DAC,如果模块内置DAC则可能不常用)
    4DACR右声道音频数据输入(通常用于连接外部DAC,如果模块内置DAC则可能不常用)
    5PLAY_LED播放指示灯,停止常亮,播放闪烁(输出高电平,LED 负极接地)
    6VCC电源输入(模块的工作电压,通常为3.6V-5V)
    7TX串口发送信号(UART异步串口的发送端,用于向外部设备发送数据)
    8RX串口接收信号(UART异步串口的接收端,用于接收外部设备发送的数据)
    9BUSY系统忙碌信号(当模块正在播放音频时,此引脚会输出特定的电平状态,指示模块处于忙碌状态)
    10IO6通用输入输出6(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    11IO5通用输入输出5(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    12IO4通用输入输出4(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    13IO3通用输入输出3(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    14IO2通用输入输出2(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    15IO1通用输入输出1(可配置为输入或输出,用于触发播放、模式选择或其他自定义功能)
    16GND地线(电源的负极,与VCC共同为模块供电)

    二、基础知识

    1、引脚连接

    BY8301-16P语音模块采用标准的UART异步串口接口(3.3V TTL电平)进行通信。这里我们使用CH32的串口三进行串口通信:

    BY8301-16P 语音模块引脚CH32 微控制器引脚/功能功能描述
    SPK1单声道无源喇叭连接喇叭的一个引脚,与SPK2共同驱动喇叭发声。
    SPK2单声道无源喇叭连接喇叭的另一个引脚,与SPK1共同驱动喇叭发声。
    VCCCH32 3.3V 输出为BY8301-16P模块提供3.3V电源。
    GNDCH32 GND 输出BY8301-16P模块的接地端。
    RXCH32 PB10BY8301-16P模块的串口接收引脚,连接到CH32的PB10,用于接收CH32发送的控制命令。

    2、通信协议

  • 数据格式:通信数据格式为1个起始位、8个数据位、无奇偶校验位和1个停止位。

  • 控制功能:通过串口命令,可以实现播放、暂停、上下曲切换、音量调节等多种操作。

  • 3、命令结构

  • 格式:所有命令都遵循特定的十六进制格式:起始码、长度、操作码、参数1、参数2、校验和、结束码。

  • 校验和:校验和通过异或(XOR)运算计算,用于确保数据传输的完整性。

  • 4、主要控制命令

    模块支持一系列控制命令,包括:

  • 播放 (0x01):启动音频播放。

  • 暂停 (0x02):暂停当前播放。

  • 音量调节 (0x05/0x06):增加或减小音量。

  • 曲目选择 (0x41):选择特定曲目进行播放。

  • 设备切换 (0x35):如果连接了多个设备,可以切换播放源。

  • 5、查询命令

    模块还允许您查询其状态:

  • 播放状态 (0x10):返回当前的播放状态(例如,正在播放、已暂停、已停止)。

  • 其他查询:您还可以查询当前的音量、均衡器模式以及文件夹中的歌曲数量。

  • 6、重要注意事项

  • 命令间隔:发送连续命令时,确保每个命令之间至少有20毫秒的间隔。

  • 组合播放命令:对于组合播放命令,间隔应小于6毫秒。

  • 三、通信程序

    1、 Usart3_Init() 串口三初始化函数

    配置CH32微控制器的USART3(通用同步/异步收发器3)进行串口通信。以下是代码的详细分解:


void Usart3_Init()

{

    //结构体定义

    GPIO_InitTypeDef  GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    NVIC_InitTypeDef  NVIC_InitStructure;


    //时钟使能

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);


    //GPIO 引脚配置

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    

    //USART3 参数配置

    USART_InitStructure.USART_BaudRate = 9600;

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    USART_InitStructure.USART_StopBits = USART_StopBits_1;

    USART_InitStructure.USART_Parity = USART_Parity_No;

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;

    USART_Init(USART3, &USART_InitStructure);

    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

    

    //中断配置

     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

     NVIC_Init(&NVIC_InitStructure);


    //使能 USART 和清除标志位

     USART_Cmd(USART3, ENABLE);

     USART_ClearFlag(USART3,USART_FLAG_TC);//清空串口3的发送标志位

}

结构体定义


这里定义了三个结构体变量,分别用于配置:


GPIO_InitStructure:GPIO引脚。

USART_InitStructure:USART3模块。

NVIC_InitStructure:嵌套向量中断控制器,用于中断配置。

时钟使能


这两行代码的作用是使能相关外设的时钟:


RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);:使能USART3模块的时钟。USART3挂载在APB1总线上。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);:使能GPIOB端口的时钟。USART3的引脚(PB10和PB11)位于GPIOB端口。

GPIO 引脚配置


这段代码配置了GPIOB的PB10引脚用于USART3通信:


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;:指定要配置的引脚是PB10。

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;:设置引脚的输出速度为50MHz,这对于高速串口通信是常见的设置。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;:将引脚模式设置为复用推挽输出。对于USART,TX(发送)引脚通常需要配置为复用推挽输出。

USART3 参数配置


这段代码配置了USART3的通信参数:


USART_BaudRate = 9600;:设置波特率为9600bps。这是BY8301-16P语音模块的常用波特率。

USART_WordLength = USART_WordLength_8b;:设置数据字长为8位。

USART_StopBits = USART_StopBits_1;:设置停止位为1位。

USART_Parity = USART_Parity_No;:禁用奇偶校验。

USART_HardwareFlowControl = USART_HardwareFlowControl_None;:禁用硬件流控制。

USART_Mode = USART_Mode_Tx|USART_Mode_Rx;:使能USART3的发送和接收功能

中断配置


这段代码配置了USART3的接收中断:


USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);:使能USART3的接收非空中断。这意味着当接收缓冲区有新的数据时,会触发中断。

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;:指定中断通道为USART3的中断。

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;:设置抢占优先级为1。

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;:设置子优先级为1。

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;:使能USART3中断。

NVIC_Init(&NVIC_InitStructure);:初始化NVIC

使能 USART 和清除标志位


USART_Cmd(USART3, ENABLE);:使能USART3模块,使其开始工作。

USART_ClearFlag(USART3,USART_FLAG_TC);:清除USART3的发送完成标志位。这通常在发送数据之前或发送数据后进行,以确保发送状态的正确性

2、 audio_proc():语音处理函数

通过USART3(串口3)向BY8301-16P语音模块发送命令,播放指定编号的音频文件。


void audio_proc(uint8_t num)

{

    // 定义一个包含串口发送命令的字节数组

    uint8_t string[]={0x7E,0x05,0x41,0x00,num,0x05^0x41^0x00^num,0xEF};


    uint8_t i = 0; // 循环计数器

    for(i=0;i<7;i++) // 循环发送7个字节的命令

    {

        USART_SendData(USART3, string[i]); // 发送当前字节

        // 等待发送完成标志位被置位,确保当前字节发送完毕才发送下一个字节

        while(  USART_GetFlagStatus(USART3, USART_FLAG_TC)==0 );

    }

}

1. 、函数声明
  • void audio_proc(uint8_t num):

  • void: 表示函数没有返回值。

  • audio_proc: 函数名称,表示“音频处理”或“播放音频”。

  • uint8_t num: 函数接收一个名为 num 的无符号8位整数作为参数。这个 num 就是你想要播放的音频文件在模块内部的编号。

  • 2. 定义串口发送命令数组
  • uint8_t string[]={0x7E,0x05,0x41,0x00,num,0x05^0x41^0x00^num,0xEF};
    这行代码定义了一个字节数组 string,它包含了发送给BY8301-16P语音模块的串口命令。根据之前对BY8301-16P串口通信协议的了解,这是一个标准的**“选曲播放”**命令。让我们逐个分析这些字节:



  • 0x7E: 起始码 (Start Code)。所有命令的开始字节。

  • 0x05: 长度 (Length)。表示从“长度”到“校验码”之间的字节数。这里是 0x05,0x41, 0x00, num,0x05^0x41^0x00^num,共5个字节。所以实际长度是 5字节。

  • 0x41: 操作码 (Operation Code)。根据手册,0x41 是“选曲播放”命令的操作码。

  • 0x00: 参数1 (Parameter 1)。在选曲播放命令中,这个通常表示文件夹编号。0x00 通常代表根目录或不区分文件夹。

  • num: 参数2 (Parameter 2)。这就是传入函数的音频文件编号。例如,如果 num 是1,模块会播放编号为1的音频文件。

  • 0x05^0x41^0x00^num: 校验和 (Checksum)。这是从“长度”字节开始到“参数2”的所有字节的异或和。0x05(长度)^ 0x41(操作码)^ 0x00(参数1)^ num(参数2)。校验和用于验证数据传输的完整性。

  • 0xEF: 结束码 (End Code)。所有命令的结束字节。

  • 3. 循环发送字节
  • uint8_t i = 0;:定义一个循环计数器 i,初始化为0。

  • for(i=0;i<7;i++): 这是一个 for 循环,将迭代7次。由于 string 数组有7个字节,这个循环会逐个发送 string 数组中的所有字节。

  • USART_SendData(USART3, string[i]);: 在每次循环中,这行代码将 string 数组中的当前字节 (string[i]) 发送给 USART3。

  • while( USART_GetFlagStatus(USART3, USART_FLAG_TC)==0 );: 这是一个阻塞等待循环。

  • USART_GetFlagStatus(USART3, USART_FLAG_TC): 这个函数用于检查 USART3 的 发送完成标志位 (Transmission Complete flag)。当 USART3 成功发送完一个字节的数据后,这个标志位会被置位。

  • ==0: 表示标志位没有被置位(即发送尚未完成)。

  • while(...): 只要 USART_FLAG_TC 标志位为0,程序就会一直停在这个 while 循环中,等待当前字节发送完毕。这样做的目的是确保每个字节都完全发送出去之后,才发送下一个字节,避免数据混乱或丢失。

  • 4、总结作用:

    audio_proc 函数的作用是:

    1. 根据传入的 num 值(音频文件编号),构造一个完整的BY8301-16P语音模块的“选曲播放”命令帧。

    2. 通过USART3(串口3)将这个命令帧中的每一个字节逐个发送出去。

    3. 在发送每个字节后,会等待直到该字节完全发送完成,才继续发送下一个字节,确保数据的正确传输。

    简单来说,调用 audio_proc(5); 就会尝试让BY8301-16P语音模块播放编号为5的音频文件。

    3、audio_volume():音量设置函数


    其主要目的是通过USART3(串口3)向BY8301-16P语音模块发送命令,用于设置播放音量。

    void audio_volume(u8 volume)

    {

        // 定义一个包含串口发送命令的字节数组

        u8 string[]={0x7e,0x04,0x31,volume,0x04^0x31^yinliang,0xef};


        u8 i; // 循环计数器

        for(i=0;i<6;i++) // 循环发送6个字节的命令

        {

            USART_SendData(USART3,string[i]); // 发送当前字节

            // 等待发送完成标志位被置位,确保当前字节发送完毕才发送下一个字节

            while(  USART_GetFlagStatus(USART3, USART_FLAG_TC)==0 );

        }

    }


    简单来说,调用 audio_volume(20); 就会尝试将BY8301-16P语音模块的音量设置为20(十六进制 0x14)。通常,音量范围是0到30(0x00到0x1E)。

    USART_SendData(USART3,string[i]); // 发送当前字节
    // 等待发送完成标志位被置位,确保当前字节发送完毕才发送下一个字节
    while( USART_GetFlagStatus(USART3, USART_FLAG_TC)==0 );
    }
    }
    简单来说,调用 audio_volume(20); 就会尝试将BY8301-16P语音模块的音量设置为20(十六进制 0x14)。通常,音量范围是0到30(0x00到0x1E)。

    注意:如何把音频文件更新进BY8301-16P语音模块,请看官方的使用说明书。


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦四级调频发射机

  • 500W MOS场效应管电源逆变器,12V转110V/220V

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章