当前位置:网站首页>如何给Arduino项目添加音乐播放功能
如何给Arduino项目添加音乐播放功能
2022-07-06 09:17:00 【XlinliY.Zhang】
(以下教程仅针对Arduino UNO、Arduino Nano等使用Atmel328P为核心的开发板)
一、蜂鸣器播放音乐
说起单片机播放音乐,大家第一个想到的应该是无源蜂鸣器或喇叭。( 因无源蜂鸣器的工作原理与扬声器相同,此处混为一谈,但实际使用仍有区别 ),无论是51、Arduino、亦或是STM32,在入门时期都会使用蜂鸣器进行播放音乐。无源蜂鸣器的应用非常广泛,小到电子贺卡,玩具,大到上世纪的康瑞达电脑,都使用无源蜂鸣器进行发声或音乐的播放。
在Arduino中,经常使用以下的函数驱动蜂鸣器:
Tone(蜂鸣器引脚, 输出的频率);// 在指定的引脚输出指定的频率使蜂鸣器发声
noTone(蜂鸣器引脚); // 停止指定引脚的PWM输出,使蜂鸣器不发声
对于这用播放音乐的方式:
优点有:
- 成本低廉,通常只需要蜂鸣器即可,对于更高的要求和更高的声音要求,只需要添加三极管和电阻,再加一个二极管保护即可。
- 电路设计简单,
缺点有:
- 占用非常多的资源,你需要一个定时器用于输出PWM,一定的空间(内部RAM\ROM或外部ROM)
- 需要占用大部分的系统时间,进行频率切换等
- 由于Arduino没有DAC,播放的音乐只是勉强能听,方波输出,和模拟输出仍有较大差别
- 对于某些IO直接驱动蜂鸣器、扬声器的教程,对于开发版而言就是炸弹,轻则烧毁IO,重则带走开发版及传感器(此处涉及电感的相关知识,有兴趣的小伙伴可以去观看B站up 罗兹新一期关于继电器的视频)
二、MP3模块播放音乐
在今天,国产的MP3模块已经非常流行了如JQ6500、JQ8900等,使用MP3模块连接单片机,既可以简单的播放音乐,又可以控制EQ、音量、随意暂停播放插播歌曲、查询歌曲名字、歌曲时长等。他的操作如同老式MP3,只需要将他连接到电脑,存放歌曲即可。
在Arduino中,经常使用以下的函数驱动MP3模块:
// 使用串口控制
dat = Serial.read();
Serial.write(dat);
// IO或单总线方式控制
delay(ms);
delayMicroseconds(us);
digitalWrite(io, LOW);
digitalWrite(io, HIGH);
对于这用播放音乐的方式:
优点有:
- 占用IO少,一个IO即可播放上百首音乐
- 占用资源少,MP3模块支持IO触发、单总线控制、串口控制等,哪怕是手动用开关都能控制,也不需要使用单片机昂贵的空间储存音频文件。
- 音频播放效果好,对比蜂鸣器,简直天差地别
- 音量大小可调,更换音频文件不需要重新烧录程序
- 电路设计简单
缺点有:
- 对比蜂鸣器,价格确实是贵了点,一套下来基本要10元左右
- 功耗更大,由于有了专用的功放和DSP、DAC等电路,功耗相比蜂鸣器会更大
三、使用解码器播放音乐
使用音频解码模块 + 功放+储存模块,这种方法在STM32中比较常见,在低端单片机中并不多见,使用VS1053 + 内存卡模块进行实时音频输出,再经过功放放大推动喇叭,这种方法仅适用于高端单片机,其不仅对单片机性能要求高,对硬件电路设计,和开发者水平同样有高要求。
在Arduino中,使用这种方式驱动代码复杂,不同型号解码器驱动方式大不相同,故此处不列出参考代码。
对于这用播放音乐的方式:
优点有:
- 不仅支持音频解码,同时还支持音频编码,说人话就是支持录音和播音。
- 音频质量会比MP3模块的好。
- 支持双声道甚至更高的声道数。
缺点有:
- 价格昂贵,需要多个芯片的配合
- 对单片机和开发者要求高
- 电路设计复杂
四、总结
综合以上
在2021年的今天使用蜂鸣器播放音乐,不仅麻烦,需要将音频文件转换为频率文件,还要浪费单片机昂贵的储存空间(如果使用内存卡,内存卡还需要内存卡模块,价格就上来了,使用EEPROM或flash,开发者还需要了解如何烧录这类芯片),冒着开发版烧毁的风险,(给你推荐这种教程的都没按什么好心);
而使用专用的驱动芯片和内存卡进行音频的播放,意义更多在于演示,无论价格还是资源占用上,亦或是对开发者知识储备的要求,都不是最优解;
使用MP3模块,价格方面不高也不低,对于知识储备要求极低。(只要你会拉高拉低单片机IO电平都能上手,这个在入门教程的blink中已经教授给你了)
五、概括
蜂鸣器适合播放提示音,价格最低,音质最差,操作麻烦
MP3模块适合播放长短音频,价格适中,音质中等,操作简单
音频解码器适合播放高品质或多声道音频,价格昂贵,音质最好,操作复杂
边栏推荐
- 共用体(union)详解【C语言】
- ESP8266通过Arduino IDE连接Onenet云平台(MQTT)
- Arduino gets the length of the array
- Time slice polling scheduling of RT thread threads
- 优先级反转与死锁
- I2C bus timing explanation
- Mysql database interview questions
- Inline detailed explanation [C language]
- Dead loop in FreeRTOS task function
- FreeRTOS 任务函数里面的死循环
猜你喜欢
Symbolic representation of functions in deep learning papers
JS Title: input array, exchange the largest with the first element, exchange the smallest with the last element, and output array.
ES6 grammar summary -- Part I (basic)
Working principle of genius telephone watch Z3
arduino UNO R3的寄存器写法(1)-----引脚电平状态变化
Cannot change version of project facet Dynamic Web Module to 2.3.
[esp32 learning-1] construction of Arduino esp32 development environment
Redis based distributed locks and ultra detailed improvement ideas
Redis based distributed ID generator
Page performance optimization of video scene
随机推荐
Use of lists
arduino JSON数据信息解析
Selective sorting and bubble sorting [C language]
Cannot change version of project facet Dynamic Web Module to 2.3.
RT-Thread的main线程“卡死”的一种可能原因及解决方案
Fashion-Gen: The Generative Fashion Dataset and Challenge 论文解读&数据集介绍
JS正则表达式基础知识学习
arduino UNO R3的寄存器写法(1)-----引脚电平状态变化
GNN的第一个简单案例:Cora分类
基于Redis的分布式ID生成器
[Red Treasure Book Notes simplified version] Chapter 12 BOM
Cannot change version of project facet Dynamic Web Module to 2.3.
C语言回调函数【C语言】
(五)R语言入门生物信息学——ORF和序列分析
FreeRTOS 任务函数里面的死循环
C语言函数之可变参数原理:va_start、va_arg及va_end
Variable parameter principle of C language function: VA_ start、va_ Arg and VA_ end
1081 rational sum (20 points) points add up to total points
锂电池基础知识
ES6 grammar summary -- Part 2 (advanced part es6~es11)