深圳市航顺芯片技术研发有限公司
直播中

最强海贼王

8年用户 1377经验值
擅长:MEMS/传感技术
私信 关注
[问答]

Arduino UNO控制板发送串口协议是如何控制语音播放器播放歌曲的

Arduino UNO控制板的硬件特性有哪些呢?
Arduino UNO控制板发送串口协议是如何控制语音播放器播放歌曲的?

回帖(1)

林俭幼

2021-11-8 09:47:38
案例主控板如不做特殊说明的话,均默认是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)模块引脚定义

  [tr]引脚名称引脚描述[/tr]
5V电源负极接5V电源负极(GND)
5V电源正极           接5V电源正极     
TXD/IO0IO触发模式下为输入引脚IO0;
UART控制模式下为TX引脚, 连接控制端(MCU)的RX;
RXD/IO1IO触发模式下为输入引脚IO1;
UART控制模式下为RX引脚, 连接控制端(MCU)的TX ;
IO2IO触发模式输入引脚IO2
IO3IO触发模式输入引脚IO3
IO4/ONE_LINEIO触发模式输入引脚IO4;One_Line一线串口控制模式数据 接收引脚
IO5IO触发模式输入引脚IO5
IO6IO触发模式输入引脚IO6
IO7IO触发模式输入引脚IO7
BUSY播放曲目时输出低电平(0V),播放结束输出高电平(3.3V)
GND参考地端(与控制端GND连接)



  • 5)IO输入输出特性


IO输入特性



符号参数最小最大单位
VIL低电平输入00.8V
VIH高电平输入2.73.3V
IO输出特性



VOL低电平输出00.33V
VOH高电平输出2.73.3V
  


  • 6)拨码开关模式配置

对应拨码开关上的编号1CON1拨到数字端为低电平(下拉)拨到ON端为高电平(上拉)
2CON2拨到数字端为低电平(下拉)拨到ON端为高电平(上拉)
3CON3拨到数字端为低电平(下拉)拨到ON端为高电平(上拉)
  
控制模式配置引脚I/O功能








CON3CON2CON1IO7IO6IO5IO4IO3IO2IO1IO0
I/O组合模式0000按键组合播放,可播放2^8-1(255)首曲目。






I/O组合模式1001电平组合播放,可播放2^8-1(255)首曲目。






I/O独立模式0010曲目8曲目7曲目6曲目5曲目4曲目3曲目2曲目1
I/O独立模式1011曲目8曲目7曲目6曲目5曲目4曲目3曲目2曲目1
UART串口模式100





RXDTXD
一线串口


RXD






标准MP3模式101


RPTEQP/P/MODEPREV/V-NEXT/V+
   注:“按键组合播放”是指IO0-IO7输出对应的电平后恢复原来的高电平,类似于按键触发一次 “电平组合播放”是指IO0-IO7输出对应的电平后保持电平不变 “I/O组合(独立)模式0”与“I/O组合(独立)模式1”的区别在于前者模式释放电平后 继续播放当前曲目至结束,后者模式释放电平后立即停止播放曲目。    二、语音模块操作说明

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


配置引脚CON3CON2CON1
电平设置100
  2. 使用引脚


5V电源负极接5V电源负极(GND)
5V电源正极接5V电源正极
TXD/IO0UART控制模式下为TX 引脚,连接控制端(MCU)的RX
RXD/IO1UART控制模式下为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(曲目序号是由存储顺序决定)
    三、案例器件准备清单

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

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

  小喇叭验证过0.8Ω5W的也能驱动
提到按键/触摸/碰撞模块是为了在案例中做语音模块的播放状态控制
杜邦线用于UNO和语音模块的供电和串口控制,以及驱动小喇叭的引脚焊接
因为模块有耳机输出口,没小喇叭情况下可以耳机听歌,常用的3.5mm有线耳机
常见的排针都是2.54间距的,跟模块孔位对得上就行,不要太纠结什么是2.54间距
    四、案例实操
  1.硬件接线
  最最最最激动人心的时刻终于到来了,这里会说明控制案例程序设计,硬件焊接的就不讲了,你们自个搞定,UNO和DY-SV5W语音模块的接线按照下面表格接线
  
主从机接线
Arduino UNODY-SV5W语音模块
5V引脚5V电源正极
GND5V电源负极
RXDTXD/IO0
TXDRXD/IO1
随意一个数字IOBUSY
/GND
--------- 华丽丽的分割线 ----------
小喇叭接线
语音模块Speaker(+)小喇叭(+)
语音模块Speaker(-)小喇叭(-)
  语音模块BUSY引脚输出歌曲播放状态的对应电平信号,根据个人实验要求接线,不是必须的
语音模块GND引脚默认连接模块的5V电源负极,只作为GND电平参考引脚,可悬空不接
需要特别注意的是小喇叭引脚有正负之分,请看好了引脚正负再接线
  


  • 主从机接线

  • 小喇叭接线

  2.代码编写

  回到代码编写方面,案例代码相对比较简单,不用加头文件,可以在任意Arduino编译平台上编写,其中串口发送简单指令进行语音模块的控制,常用指令如下表所示,需要注意的是要以十六进制格式发送数据。
  [tr]控制功能发送指令(十六进制)[/tr]
播放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)发送的是 1,7,0 这3个字符,print(0xAA,HEX)发送的是 A,A 这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函数,少踩坑。
    五、案例实现
  这个靠你们自个脑补了,上不来视频,语音模块支持耳机播放和小喇叭播放,但接上小喇叭后耳机就听不到耳音了,反过来也是一样,不能同时支持两端输出。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分