Arduino案例实操 -- 语音播放模块(DY-SV5W)

案例主控板如不做特殊说明的话,均默认是Arduino UNO控制板。
本次实验以UNO发送串口协议控制语音播放器播放歌曲,语音播放模块选型DY-SV5W。


一、硬件选择

1. Arduino UNO

Arduino UNO板子,啥子东西你懂的,不做详细介绍,略过。

2. DY-SV5W

  • 1)硬件概述

DY-SV5W是一款智能语音模块,集成IO分段触发,UART串口控制,ONE_line 单总线串口控制,标准MP3等7种工作模式;板载5W D类功放,可直接驱动4Ω,3~5W喇叭; 支持MP3,WAV解码格式,最大支持32G TF卡存储,可通过USB数据线连接电脑更新TF 卡存储 音频文件。

  • 2)硬件特性

1、支持MP3、WAV解码格式。
2、支持采样率(KHz):8/11.025/12/16/22.05/24/32/44.1/48。
3、24位DAC输出,动态范围支持90dB,信噪比支持85dB。
4、完全支持FAT16/FAT32文件系统,最大支持32G的TF卡。
5、自带5W D类功放,可直接驱动4Ω,3~5W喇叭。
6、支持UART串口控制语音播报功能,可控制播放,暂停,选曲,音量加减等功能,最大选曲65535 首曲目,波特率9600 bit/s。
7、支持IO触发播放功能,8个IO 口单独触发8首曲目或8个IO口组合触发255首曲目。
8、支持One_line单总线串口控制,可控制播放,暂停,选曲,音量加减等功能。
9、支持3个配置IO 进行多达7种工作模式选择。

  • 3)模块接口功能说明

在这里插入图片描述

  • 4)模块引脚定义
引脚名称 引脚描述
5V电源负极 接5V电源负极(GND)
5V电源正极
接5V电源正极
TXD/IO0 IO触发模式下为输入引脚IO0;
UART控制模式下为TX引脚, 连接控制端(MCU)的RX;
RXD/IO1 IO触发模式下为输入引脚IO1;
UART控制模式下为RX引脚, 连接控制端(MCU)的TX ;
IO2 IO触发模式输入引脚IO2
IO3 IO触发模式输入引脚IO3
IO4/ONE_LINE IO触发模式输入引脚IO4;One_Line一线串口控制模式数据 接收引脚
IO5 IO触发模式输入引脚IO5
IO6 IO触发模式输入引脚IO6
IO7 IO触发模式输入引脚IO7
BUSY 播放曲目时输出低电平(0V),播放结束输出高电平(3.3V)
GND 参考地端(与控制端GND连接)
  • 5)IO输入输出特性
IO输入特性
符号 参数 最小 最大 单位
VIL 低电平输入 0 0.8 V
VIH 高电平输入 2.7 3.3 V
IO输出特性
VOL 低电平输出 0 0.33 V
VOH 高电平输出 2.7 3.3 V
  • 6)拨码开关模式配置
对应拨码开关上的编号 1 CON1 拨到数字端为低电平(下拉) 拨到ON端为高电平(上拉)
2 CON2 拨到数字端为低电平(下拉) 拨到ON端为高电平(上拉)
3 CON3 拨到数字端为低电平(下拉) 拨到ON端为高电平(上拉)
控制模式 配置引脚 I/O功能
CON3 CON2 CON1 IO7 IO6 IO5 IO4 IO3 IO2 IO1 IO0
I/O组合模式0 0 0 0 按键组合播放,可播放2^8-1(255)首曲目。
I/O组合模式1 0 0 1 电平组合播放,可播放2^8-1(255)首曲目。
I/O独立模式0 0 1 0 曲目8 曲目7 曲目6 曲目5 曲目4 曲目3 曲目2 曲目1
I/O独立模式1 0 1 1 曲目8 曲目7 曲目6 曲目5 曲目4 曲目3 曲目2 曲目1
UART串口模式 1 0 0 RXD TXD
一线串口 RXD
标准MP3模式 1 0 1 RPT EQ P/P/MODE PREV/V- NEXT/V+
注:“按键组合播放”是指IO0-IO7输出对应的电平后恢复原来的高电平,类似于按键触发一次 “电平组合播放”是指IO0-IO7输出对应的电平后保持电平不变 “I/O组合(独立)模式0”与“I/O组合(独立)模式1”的区别在于前者模式释放电平后 继续播放当前曲目至结束,后者模式释放电平后立即停止播放曲目。

二、语音模块操作说明

语音模块可以控制的模式如上表中7种模式,当你有幸拿到这块板的时候想必也拿到了厂商给的模块配套使用资料,该文章中博主就比较实用的串口指令模式做简单说明。

1. UART模式拨码开关设置

配置引脚 CON3 CON2 CON1
电平设置 1 0 0

2. 使用引脚

5V电源负极 接5V电源负极(GND)
5V电源正极 接5V电源正极
TXD/IO0 UART控制模式下为TX 引脚,连接控制端(MCU)的RX
RXD/IO1 UART控制模式下为RX引脚,连接控制端(MCU)的TX
BUSY 播放曲目时输出低电平(0V),播放结束输出高电平(3.3V)
GND 参考地端(与控制端GND连接)

3. 通信格式

采用全双工串口通信;
波特率为9600,数据位:8 ,停止位1位,检验位 N。
起始码-指令类型-数据长度(n)-数据1-数据 n-和检验(SM)

※ 指令码 :固定为 AA。
※ 指令类型 : 用来区分指令类型。
※ 数据长度:指令中的数据的字节数。
※ 数据 :指令中的相关数据,当数据长度为 1时,表示只有CMD,没有数据位。
※ 和检验 :为之前所有字节之和的低8位,即起始码到数据相加后取低 8位。
※ 数据格式:发送的数据或命令,高8位数据在前,低 8位在后。

4. 通信机制

1)我方做为从机处理,上电默认等待状态,所有播放操作全由主机控制。
2)从机不会主动发起通信,所有通信都是由主机发起。
3)串口是3.3V的TTL 电平,如果主机系统是 5V电平请在中间串1K 电阻。
4)如未特别说明,协议中所有数据都是表示十六进制数据。

实操验证了在语音模块串口RX、TX电路已焊接了1k电阻,无需考虑主机和从机的串口电平问题

5. 协议约定

以下是模块芯片返回和能识别的数据定义。
1)播放状态定义 :系统上电处于停止状态。
※ 00(停止) 01(播放) 02(暂停)

2) 盘符定义: 切换盘符后处于停止状态。
※ USB:00 SD:01 FLASH:02 NO_DEVICE:FF

3)音量:音量总共为 31级,0-30级,上电默认为 20级。

4)播放模式定义:上电默认为单曲停止。
※ 全盘循环(00):按顺序播放全盘曲目,播放完后循环播放。
※ 单曲循环(01):一直循环播放当前曲目。
※ 单曲停止(02):播放完当前曲目一次停止。
※ 全盘随机(03):随机播放盘符内曲目。
※ 目录循环(04):按顺序播放当前文件夹内曲目,播放完后循环播放,目录不 包含子目录。
※ 目录随机(05): 在当前目录内随机播放,目录不包含子目录。
※ 目录顺序播放(06):按顺序播放当前文件夹内曲目,播放完后停止,目录不 包含子目录。
※ 顺序播放(07):按顺序播放全盘曲目,播放完后停止。

5)EQ定义:上电默认 EQ 为NORMAL(00)。
※ NORMAL(00) POP(01) ROCK(02) JAZZ(03) CLASSIC(04)

6)DAC输出通道定义:上电默认为 MP3播放通道(00)。
※ MP3播放通道(00): 播放MP3通道,DAC输出的声音为音乐播放的声音。
※ AUX通道(01):DAC输出的声音为P26和P27 输入的声音。
※ MP3+AUX(02):AUX通道MP3同时打开,DAC输出的声音是音乐播放的声 音和P26、P27输入的声音混合输出。

7)组合播放定义:组合播放是按文件名来组合,文件要求存储在“ZH”文件夹下, 可以把要组合的文件名称更改为两个字节的名称,一般建议用数字表示。如: 01.mp3,02.mp3,也可以用两个字母或一个汉字命名。

6. 通信指令(部分常用指令,非全部)

查询播放状态(01)
指令:AA 01 00 AB
返回:AA 01 01 播放状态 SM
说明:在任何时候都可以查询当前的播放状态
播放状态:00 停止;01播放;02 暂停

播放(02)
指令:AA 02 00 AC
返回:无
说明:在任何时候发此命令都会从头开始播放当前曲目

暂停(03)
指令:AA 03 00 AD
返回:无

停止(04)
指令:AA 04 00 AE
返回:无

上一曲(05)
指令:AA 05 00 AF
返回:无

下一曲(06)
指令:AA 06 00 B0
返回:无

指定曲目(07)
指令:AA 07 02曲目高 曲目低 SM
返回:无
例如: AA 07 02 00 08 BB 指定播放当前盘符第 8首,曲目数从1-65535(曲目序号是由存储顺序决定)


三、案例器件准备清单

来看看你准备的东西的备齐了没有~

  1. Arduino UNO控制板 * 1
  2. DY-SV5W语音模块 * 1
  3. 按键模块/触摸模块/碰撞模块 * 1
  4. 4Ω小喇叭(3-5W)* 1
  5. micro SD卡 * 1(存放歌曲)
  6. 有线耳机 * 1
  7. USB下载线 * 1(下载案例程序,USB供电用)
  8. 7.5V DC电源 * 1(符合供电范围的都可,独立供电用)
  9. 电烙铁 * 1
  10. 焊锡若干
  11. 杜邦线若干(公对公,公对母)
  12. 排针若干(2.54间距,焊接语音模块引脚)

小喇叭验证过0.8Ω5W的也能驱动
提到按键/触摸/碰撞模块是为了在案例中做语音模块的播放状态控制
杜邦线用于UNO和语音模块的供电和串口控制,以及驱动小喇叭的引脚焊接
因为模块有耳机输出口,没小喇叭情况下可以耳机听歌,常用的3.5mm有线耳机
常见的排针都是2.54间距的,跟模块孔位对得上就行,不要太纠结什么是2.54间距


四、案例实操

1.硬件接线

最最最最激动人心的时刻终于到来了,这里会说明控制案例程序设计,硬件焊接的就不讲了,你们自个搞定,UNO和DY-SV5W语音模块的接线按照下面表格接线

主从机接线
Arduino UNO DY-SV5W语音模块
5V引脚 5V电源正极
GND 5V电源负极
RXD TXD/IO0
TXD RXD/IO1
随意一个数字IO BUSY
/ GND
--------- 华丽丽的分割线 ----------
小喇叭接线
语音模块Speaker(+) 小喇叭(+)
语音模块Speaker(-) 小喇叭(-)

语音模块BUSY引脚输出歌曲播放状态的对应电平信号,根据个人实验要求接线,不是必须的
语音模块GND引脚默认连接模块的5V电源负极,只作为GND电平参考引脚,可悬空不接
需要特别注意的是小喇叭引脚有正负之分,请看好了引脚正负再接线

  • 主从机接线
    主从机接线

  • 小喇叭接线
    在这里插入图片描述

2.代码编写

回到代码编写方面,案例代码相对比较简单,不用加头文件,可以在任意Arduino编译平台上编写,其中串口发送简单指令进行语音模块的控制,常用指令如下表所示,需要注意的是要以十六进制格式发送数据。

控制功能 发送指令(十六进制)
播放 AA 02 00 AC
暂停 AA 03 00 AD
停止 AA 04 00 AE
结束播放 AA 10 00 BA

案例源码:

//bool变量,语音模块是否处于播放状态的状态量
bool mp3_control = false;

//setup函数
void setup()
{
    
    	
	//模块状态控制传感器引脚(按键/触摸传感器/碰撞传感器)
	pinMode(2, INPUT);
	//设置串口波特率,语音模块串口波特率为9600,统一波特率
	Serial.begin(9600);
}

void loop()
{
    
    
	//控制模块播放歌曲(案例所用触摸传感器高电平触发)
	if((digitalRead(2) == HIGH)&&(mp3_control == false))
	{
    
    
		//延时去抖
		delay(500);
		
		//修改状态量mp3_control为true(播放状态)
		mp3_control = true;

		//发送播放指令  AA 02 00 AC
		Serial.write(0xAA);
		Serial.write(0x02);
		Serial.write(0x00);
		Serial.write(0xAC);
		delay(1000);
		
		//发送(当前目录)顺序播放指令 AA 18 01 07 CA
		Serial.write(0xAA);
		Serial.write(0x18);
		Serial.write(0x01);
		Serial.write(0x07);
		Serial.write(0xCA);
	}else
	//控制模块暂停播放(案例所用触摸传感器高电平触发)
	if((digitalRead(2) == HIGH)&&(mp3_control == true))
	{
    
    
		//延时去抖
		delay(500);
		//修改状态量mp3_control为false(暂停状态)
		mp3_control = false;

		//发送暂停指令 AA 03 00 AD
		Serial.write(0xAA);
		Serial.write(0x03);
		Serial.write(0x00);
		Serial.write(0xAD);
	}
	
}

3.爬坑(print函数和write函数)

看过案例代码后你可能觉得这个案例已经学会了,但这里面有个坑你需要知道,就是串口的print函数和write函数,这两个函数在部分人之间还是存在着争议的,先丢个arduino函数的官网说明上来。

print函数
Prints data to the serial port as human-readable ASCII text.(将数据显示为人能读懂的ASCII文本输出到串口) This command can take many forms. Numbers are printed using an ASCII character for each digit.(对于数值,采用ASII码显示每个数字)

write函数
Writes binary data to the serial port. (将二进制数据写入串口)This data is sent as a byte or series of bytes;(数据以字节形式发送出去)to send the characters representing the digits of a number use the print() function instead.(如要发送单个数字(0-9)的字符请使用print函数代替)

print函数是arduino入门时就接触到的函数,对于程序调试和串口数据显示来说是很实用的,但在串口设备之间进行数据传输,print函数就显然是个大坑了。
在本次案例中明确说到语音模块的串口指令需要以十六进制的形式发送,像发送指令的协议头0xAA,经验不足的人可能在代码中会这么写

Serial.print(0xAA);

在发送给串口设备发现指令没得到体现之后他可能回去用串口监视器查看程序的串口输出是什么,结局就是这样的

Serial.print(0xAA);

//串口实际输出(0xAA = 170)
170

然后你可能这么写

Serial.print(0xAA,HEX);

串口输出的结果貌似符合要求

Serial.print(0xAA,HEX);	//HEX为数据转十六进制输出

//串口实际输出
AA

//然而在串口用十六进制接收的话
41 41
//A = 65(ASCII表) = 41(65的十六进制)

彻底懵圈了,下面简单说一下,print函数和println函数,发送的内容都是以单个字符的形式往外发送的,例如print(0xAA)发送的是 170 这3个字符,print(0xAA,HEX)发送的是 AA 这2个字符,这样在串口转十六进制接收时print(0xAA)是以3个十六进制数显示,print(0xAA,HEX)则是以2个十六进制数显示,这达不到我们的串口十六进制接收收到AA的要求。

串口改用write函数发送0xAA

Serial.write(0xAA);

串口收到的数据

Serial.write(0xAA);

//十六进制接收
AA

这样发送案例语音模块播放指令就是这样的

//AA 02 00 AC
Serial.write(0xAA);
Serial.write(0x02);
Serial.write(0x00);
Serial.write(0xAC);

//串口十六进制接收
AA 02 00 AC

关于串口发送指令的函数说明有点啰嗦了,但希望你们可以看明白,什么时候该用print函数,什么时候该用write函数,少踩坑。


五、案例实现

这个靠你们自个脑补了,上不来视频,语音模块支持耳机播放和小喇叭播放,但接上小喇叭后耳机就听不到耳音了,反过来也是一样,不能同时支持两端输出。

猜你喜欢

转载自blog.csdn.net/qq_36955622/article/details/103512824