stm32教程:MP3语音播报模块(LX-TRIG-MP3-V6.0)

早上好啊,大佬们。前不久出于一些机缘巧合接触了一款MP3语音播报模块,但是当时学习这个的时候在网上没有找到什么关于它的文章,所以我研究了一下这个语音播报模块,然后写了这篇文章,也作为自己之后复习用的材料,可能会有遗漏的地方,各位大佬们也小白兔修正修正。

先来看看它长什么样子吧!~

这个模块的使用很简单,咱们一点点来介绍。

接口介绍

它有四处接口,microUSB接口,排针接口,3.5mm接口,TF卡接口,P2喇叭接口我们一个个来讲讲。

microUSB接口
可用于USB供电,亦可出入电脑使模块当U盘使用,可以读写TF卡里内容。
此时注意,如果接入电脑,模块不能当播放器播放音频,此时相当于U盘。
排针接口

A1到A9共9个触发口

普通模式9个触发口对应触发9首音频 编码模式可以触发31首音频

5V针和micrUSB输入正接通,所有GND连在一起,所以接哪里都一样。
BY为播放状态指示,播放输出低电平,不播报输出高电平
KEY键,辅助键接按键控制 播放 暂停。
3.5mm接口
接耳机或其他带功放的影响设备(有源喇叭)。
TF卡接口
插入最大16GTF卡。
P2喇叭接口
5W功放输出,接喇叭(喇叭不分正负极)如果使用3W喇叭,将声音调小一些,避免超功率而声音失真。

相关参数

供电:直流 5V 1A
触发端口:9 个
触发歌曲:直接触发 9 首,单片机触发 31 首
喇叭参数:0-5 瓦 4-8 欧 (音量可调)
支持最大内存:16G
以上这一些内容都来源于商家给的资料,然后我会把商家的资料都发出来,然后我们下面就来看看怎么使用吧。

播放模式

单播放模式:

模块具备 9 个直接触发端口,是 A1-A9 这 9 根排针。这 9 个端口同时对应9 首 MP3,分别是第一首到第九首,先放入 TF 卡的为第一首。
触发方式为,例如 A1 口,只要向 A1 口提供 1 个低电平50ms以上,就马上进行播放第一首MP3。低电平为 0V 电压,可以将板上的 GND去触发。或者直接用单片机 IO 口触发。

编码触发模式

本模块除了直接触发 9 首 MP3 的功能外还具备 31 首 MP3 的点播功能。但这功能需要结合单片机才能完成操作。
在给模块上电之前,先把 A10 接地,这样在上电后就切换为编码模式。其中 A1-A5 为编码端口,为二进制编码的反码方式,A1为第一位。
例如说:
要播放第10首,那就是 01010 也就是 A2 和 A4 置低电平。

TF卡文件存放

首先,先让电脑能够读取到TF卡,可以采取两种方式—— microUSB连接 || 读卡器读取。

然后在TF卡里创建两个文件夹,一个是01,另一个是99。这个名字一定不能换。

01文件夹 —— 后续引脚触发的音频文件夹

99文件夹 —— 通电就触发的音频文件夹

 后面的任务就是准备我们所需要播放的音频文件。

可以直接下载音乐,或者如果你想要用自定义的语音,可以直接在下面的网站里进行文字转语音。

在线免费文字转语音 - TTSMaker官网 | 马克配音

就是这么个使用方法。


99文件夹

先来讲一下99文件夹吧,这个比较简单。

这个只需要你在99的文件夹下放上音频,然后通上电就会播放了。

ok,这个文件夹就没什么好说的了。


下面来说说01文件夹的播放。

单播放模式

接线:

将 lx-trig-mp3-v6.0 的 5V 和 GND 接到stm32的 5V 和 GND 然后从stm32的GND引出一条线

5V可以使用st-link上面的5V,芯片提供的5V电压一般还是3V3的,虽然也能用,但还是5V的会更好一点。

将喇叭接到P2口上。

TF内容

操作

将GND引出来的线分别接触A1,A2,A3。然后就会分别播放001,002,003三个音频。

但是用芯片供电不是特别的好,建议还是用电源模块供电。


stm32控制下的单播放模式

到这里,我们就已经尝试了它的单播放模式,但是我们也可以用stm32的GPIO改变高低电平进行控制,那这又是怎么个事儿呢,下面我们来写写看吧。

首先,我们先复制一个工程模板。然后在Hardware文件夹下新建 MP3.c 和 MP3.h 两个文件夹。

我准备了三个音频,在TF卡中的存储如下:

第一步,打开我们需要用的GPIO口,也就是 stm32上 连接 MP3模块上的A1等引脚 的口。在这里我们使用stm32上的 PB5,PB6,PB7

这个在前面我们已经学了,来看看怎么个事儿吧~

MP3.c ——

#include "stm32f10x.h"                  // Device header

void MP3_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开GPIOB的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO的模式改为推挽输出。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5| GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB,GPIO_Pin_5); // MP3的这些引脚初始需要为高电平
	GPIO_SetBits(GPIOB,GPIO_Pin_6);
	GPIO_SetBits(GPIOB,GPIO_Pin_7);
}

然后,我们就可以通过改变GPIO口的高低电平实现播放控制。

在MP3.h里对MP3_Init() 进行声明;

MP3.h ——

#ifndef __MP3_H
#define __MP3_H

void MP3_Init(void);



#endif

main.h ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h


int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉低,也就是播放音频。
	
	
	while(1)
	{
		
	}
	
}

这样我们就能播放第一个音频了。

然后我们将准备3个音频都播放一下吧。

main.c ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h


int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉低,也就是播放音频。
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	while(1)
	{
		
	}
	
}

大家看这个代码,应该没错吧,但是大佬们会发现我们的MP3只会播放第一个音频,后面的两个音频还是不会播放。

一次触发命令

这是因为——

模块上电后A1-A10脚默认都是高电平,也就是有5V的电压,如果要触发其中的某个脚,就必须在这个脚为高电平的状态下, 再拉低电平50毫秒以上 (大于50ms就可以,就是拉低一天也是算一个触发),这时就算一个触发命令,如果该脚要再次触发, 必须保证触发前该脚高电平状态下超过50毫秒以上

也就是说,它需要50ms的时间去反应我们的信号输入,而且,他需要我们将电平拉高之后才会去处理我们的下一个信号。

那么,也就是说我们如果想要播放多个音频,现在需要做的就是写一个将电平拉高的语句,并且每个语句之间需要50ms的延时。

说到延时,我们就需要用到之前写的Delay函数了,不知道的大佬们可以看看小白兔之前的一篇文章,也就是讲Delay()函数的那一篇。

stm32教程:Delay函数 及 引脚复用重定义_stm32 寄存器delay-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/sikimayi/article/details/143496013?spm=1001.2014.3001.5501那么我们后面的思路就很清晰了。

代码修改

首先导入Delay的代码。

main.c ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h
#include "Delay.h"


int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉低,也就是播放音频。
	Delay_ms(100); //给100ms的延时,略多于50ms即可
	GPIO_SetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉高,便于下一次的触发
	Delay_ms(100);
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	GPIO_SetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	Delay_ms(100);
	GPIO_SetBits(GPIOB,GPIO_Pin_7);
	Delay_ms(100);
	
	while(1)
	{
		
	}
	
}

大家把这个代码再烧进去,会发现还是只会播放一个音频,但是现象变了,它播放的是最后一个音频,但是在播放之前会有一些杂音。

其实这个很容易就明白,前面的那些杂音就是前两个音频,因为,我们中间的延时太短,在前面的音频播放完之前就会被后面的音频覆盖掉,最后一个音频会因为后面没有将它覆盖的音频,所以会被播放出来。

但是,现在对于代码而言,我们已经成功了。

那如果我们需要播放完整的音频,只需要将中间的延时加长到能够播放完音频就可以。

例如说,我的第一个音频时长是3s,那我只需要将第一个和第二个信号传递之间的时间加长到3s就可以了。

main.c ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h
#include "Delay.h"


int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉低,也就是播放音频。
	Delay_ms(100); //给100ms的延时,略多于50ms即可
	GPIO_SetBits(GPIOB,GPIO_Pin_5); //将PB5的电平拉高,便于下一次的触发
	Delay_s(3);
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	GPIO_SetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	Delay_ms(100);
	GPIO_SetBits(GPIOB,GPIO_Pin_7);
	Delay_ms(100);
	
	while(1)
	{
		
	}
	
}

这样我的第一个音频就能完整播放了。

OK,那么我们单播放模式就讲完了,下面我们来说说编码模式吧~


编码模式

MP3模块通电之后默认打开的是单播放模式,那么我们需要使用编码模式,第一步就是在通电的时候将 A10口接地。

接线:

5V —— st-link 的 5V

GND —— stm32 的 GND

A1 —— PB5

A2 —— PB6

A3 —— PB7

A4 —— PB8

A5 —— PB9

A10 —— stm32 的 GND

其余引脚不用接

TF卡内容,和前面一样,大家需要多少就准备多少即可,可以不用按照顺序。

不用一定一个个编码下来。

代码

MP3.c ——

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void MP3_Reset(void) //便于重置引脚口,直接写一个所有引脚全部重置的函数
{
	GPIO_SetBits(GPIOB,GPIO_Pin_5);
	GPIO_SetBits(GPIOB,GPIO_Pin_6);
	GPIO_SetBits(GPIOB,GPIO_Pin_7);
	GPIO_SetBits(GPIOB,GPIO_Pin_8);
	GPIO_SetBits(GPIOB,GPIO_Pin_9);
}


void MP3_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开GPIOB的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO的模式改为推挽输出。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5| GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	MP3_Reset();
}


void A1_ON(void)
{
	// 1 的二进制是 00001,也就是只需要将 A1 拉低即可。
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	Delay_ms(100);
	MP3_Reset();
}

void A2_ON(void)
{
	// 2 的二进制是 00010
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	MP3_Reset();
}

void A3_ON(void)
{
	// 3 的二进制是 00011
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	MP3_Reset();
}

void A12_ON(void)
{
	// 12 的二进制是 01100
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
	Delay_ms(100);
	MP3_Reset();
}

void A25_ON(void)
{
	// 25 的二进制是 11001
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
	GPIO_ResetBits(GPIOB,GPIO_Pin_9);
	Delay_ms(100);
	MP3_Reset();
}

然后在MP3.h上进行声明,也就是——

MP3.h ——

#ifndef __MP3_H
#define __MP3_H

void MP3_Reset(void); //MP3_Reset在后面几乎不会用,可以选择不声明也没事
void MP3_Init(void);

void A1_ON(void);
void A2_ON(void);
void A3_ON(void);
void A12_ON(void);
void A25_ON(void);

#endif

然后,我们就能在main.c里面开始播放我们的音频了。

main.c ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h
#include "Delay.h"


int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	
	A12_ON(); //播放第4个音频
	Delay_s(1);
	
	A25_ON(); //播放第5个音频
	Delay_s(1);
	
	A1_ON(); //播放第1个音频
	Delay_s(3);
	
	A2_ON(); //播放第2个音频
	Delay_s(1);
	
	A3_ON(); //播放第3个音频
	Delay_s(1);
	
	
	while(1)
	{
		
	}
	
}

OK了,到这里大佬们应该都会用LX-TRIG-MP3这个模块了吧。


然后下面我们在来说一下它的其它一些内容,也就是BY口和KEY两个BY

BY口

首先对于BY口,它是一个输出口,也就是播放状态指示,播放输出低电平,不播报输出高电平。

那么我们可以初始化一个GPIO口,将它改为上拉输入模式。

为了更好地看现象,我们加上一个OLED来显示BY口的输出。

接线:

5V —— st-link 的 5V

GND —— stm32 的 GND

A1 —— PB5

A2 —— PB6

A3 —— PB7

A4 —— PB8

A5 —— PB9

A10 —— stm32 的 GND

BY —— PA1

其余引脚不用接

代码

下面来看代码吧,直接——

MP3.c ——

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void MP3_Reset(void) //便于重置引脚口,直接写一个所有引脚全部重置的函数
{
	GPIO_SetBits(GPIOB,GPIO_Pin_5);
	GPIO_SetBits(GPIOB,GPIO_Pin_6);
	GPIO_SetBits(GPIOB,GPIO_Pin_7);
	GPIO_SetBits(GPIOB,GPIO_Pin_8);
	GPIO_SetBits(GPIOB,GPIO_Pin_9);
}


void MP3_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开GPIOA的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO的模式改为推挽输出。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5| GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //GPIO的模式改为上拉输入。
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	MP3_Reset();
}

/*
单播放模式
*/

void A1_ON(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	Delay_ms(100);
	MP3_Reset();
}
void A2_ON(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	MP3_Reset();
}
void A3_ON(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	Delay_ms(100);
	MP3_Reset();
}


/*
编码模式
*/

/*
void A1_ON(void)
{
	// 1 的二进制是 00001,也就是只需要将 A1 拉低即可。
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	Delay_ms(100);
	MP3_Reset();
}

void A2_ON(void)
{
	// 2 的二进制是 00010
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	MP3_Reset();
}

void A3_ON(void)
{
	// 3 的二进制是 00011
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	GPIO_ResetBits(GPIOB,GPIO_Pin_6);
	Delay_ms(100);
	MP3_Reset();
}

void A12_ON(void)
{
	// 12 的二进制是 01100
	GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
	Delay_ms(100);
	MP3_Reset();
}

void A25_ON(void)
{
	// 25 的二进制是 11001
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
	GPIO_ResetBits(GPIOB,GPIO_Pin_9);
	Delay_ms(100);
	MP3_Reset();
}
*/

int BY_Get(void)
{
	return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1);
}

MP3.h ——

#ifndef __MP3_H
#define __MP3_H

void MP3_Reset(void); //MP3_Reset在后面几乎不会用,可以选择不声明也没事
void MP3_Init(void);

/*
单播放模式
*/
void A1_ON(void);
void A2_ON(void);
void A3_ON(void);

/*
编码模式
*/

/*
void A1_ON(void);
void A2_ON(void);
void A3_ON(void);
void A12_ON(void);
void A25_ON(void);
*/

int BY_Get(void);

#endif

main.c ——

#include "stm32f10x.h"                  // Device header
#include "MP3.h" //导入MP3.h
#include "Delay.h"
#include "OLED.h"

int by;

int main()
{
	MP3_Init(); //打开MP3引脚的GPIO口的初始化
	OLED_Init(); //打开OLED的初始化
	
	OLED_ShowString(1, 1, "BY:", OLED_8X16);
	
	by = BY_Get();
	OLED_ShowNum(1, 16, by, 1, OLED_8X16);
	OLED_Update();
	
	Delay_s(10);
	
	A1_ON(); //播放第1个音频
	by = BY_Get();
	OLED_ShowNum(8, 16, by, 1, OLED_8X16);
	OLED_Update();
	
	while(1)
	{
		
	}
	
}

大家可以试一下,在一开始输出为1, 后面为0。


key口的内容,我没有看得很懂,在商家给的pdf中说用按键来控制,但我没有理解什么意思,这里就不丢人显眼了,希望路过的大佬能教一下小白兔。

这里最后提一个东西,本篇文章就结束了。

就是在lx-mp3上有个焊点,将这里焊上,它就是单曲循环模式,就是原本是播放完就会停下来,但是焊上之后它在播放完会重新进行播放。


总结

那么,本篇的内容就是这些,总体来说lx-MP3还是比较容易的一个语音播报模块,大佬们如果需要MP3播报的话,可以考虑一下这个模块,但是它没有语音识别的功能,还是有些限制的。

按照惯例,小白兔在这里提供一下本期所写的代码,以及商家提供的资料。
链接:https://pan.quark.cn/s/dea0672b3b9a
提取码:VBVC

那么Bye Bye~,我们下期见咯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑不拉几的小白兔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值