摘  要

当前手机听音普遍存在内存占用多、便携性差、在线播放需会员等问题,专用小型音乐播放器需求凸显。STM32F103C8T6单片机因高性能、低功耗优势,成为实现多功能专用播放器的理想核心,为满足轻量化、精准适配听音需求,开展本设计研究。

本研究以STM32F103C8T6最小系统为核心,搭建集成MP3模块、SD卡存储、独立按键、七彩LED灯及蓝牙模块的播放系统。硬件层面完成各模块电路连接,配置GPIO口、USART串口及TIM定时器实现按键中断、数据通信与LED灯PWM驱动;软件层面移植FatFs文件系统,实现SD卡音乐读取、索引及自动播放,开发MP3模块驱动,编写按键全功能控制(开关机、切歌等)与蓝牙指令解析逻辑;通过系统调试优化灯光与音乐联动效果,解决双控指令响应优先级问题。

该设计摆脱手机内存依赖,双控模式适配多场景使用,灯光联动提升听音沉浸感。以低成本实现功能集成,精准满足用户纯粹听音需求,同时为嵌入式音频设备小型化、实用化研发提供可行方案,具备较高应用推广价值。

关键词:STM32F103C8T6;音乐播放器;单片机;蓝牙控制;SD卡存储

 

 

Abstract

Currently, mobile phone audio playback is plagued by issues such as high memory usage, poor portability, and the need for subscriptions for online playback, making the demand for dedicated small music players increasingly prominent. The STM32F103C8T6 microcontroller, with its advantages of high performance and low power consumption, has become an ideal core for realizing multi-functional dedicated players. To meet the needs of lightweight and accurately adapted audio playback, this design research is carried out.

This study takes the STM32F103C8T6 minimum system as the core and builds a playback system integrating an MP3 module, SD card storage, independent keys, RGB LED lights, and a Bluetooth module. At the hardware level, the circuit connection of each module is completed, and GPIO ports, USART serial ports, and TIM timers are configured to realize key interrupts, data communication, and PWM driving of LED lights. At the software level, the FatFs file system is ported to achieve music file reading, indexing, and automatic playback on the SD card; MP3 module drivers are developed, and full-function key control (power on/off, track switching, etc.) and Bluetooth command parsing logic are written. Through system debugging, the linkage effect between lights and music is optimized, and the response priority issue of dual-control commands is resolved.

This design frees users from reliance on mobile phone memory, and the dual-control mode adapts to various usage scenarios, while the light-music linkage enhances the immersive audio experience. It achieves functional integration at low cost, accurately meets users' pure audio playback needs, and provides a feasible solution for the miniaturization and practicalization of embedded audio devices, featuring high application and promotion value.

Key words: STM32F103C8T6; Music Player; Microcontroller Unit (MCU); Bluetooth Control; SD Card Storage

 

目  录

摘  要...................................... 3

Abstract.................................... 4

目  录...................................... 5

1  绪论..................................... 8

1.1  选题背景和意义..................... 8

1.1.1  选题背景..................... 8

1.1.2  选题意义..................... 8

1.2  国内外研究现状..................... 9

1.2.1  国内研究现状................. 9

1.2.2  国外研究现状................. 9

1.3  研究方法.......................... 10

1.4  研究方主要内容.................... 10

2  系统设计方案............................ 12

2.1  主要模块方案选择.................. 12

2.1.1  主控芯片方案选择............ 12

2.1.2  按键模块方案选择............ 12

2.1.3  语音识别模块方案选择........ 13

2.2  整体系统框图设计.................. 14

2.3  本章小结.......................... 15

3  系统硬件设计............................ 16

3.1  单片机最小系统.................... 16

3.1.1  主控模块电路................ 16

3.1.2  晶振电路.................... 16

3.1.3  复位电路.................... 17

3.1.4  电源电路.................... 18

3.2  独立按键模块电路.................. 18

3.3  MP3音乐播放模块电路............... 19

3.4  语音识别模块电路.................. 19

3.5  本章小结.......................... 20

4  系统软件设计............................ 21

4.1  编程软件介绍...................... 21

4.2  主程序流程设计.................... 21

4.3  独立按键流程设计.................. 22

4.4  本章小结.......................... 23

5  实物测试................................ 24

5.1  实物整体焊接测试.................. 24

5.2  MP3播放实物测试................... 24

5.2.1  K1按键(暂停/播放)......... 25

5.2.2  K2按键(上一曲)............ 26

5.2.3  K3按键(下一曲)............ 26

5.2.4  K4按键(音量+)............. 27

5.2.5  K5按键(音量-)............. 27

5.2.6  K6按键(播放模式切换)...... 28

5.3  本章小结.......................... 28

致谢....................................... 30

参考文献................................... 31

附录....................................... 32

附录A:  原理图........................ 33

附录B:  PCB板........................ 34

1  绪论

1.1  选题背景和意义

1.1.1  选题背景

随着便携式音频设备的普及,个性化、低成本的小型音乐播放装置成为消费电子领域的实用化研究方向。传统音乐播放设备或依赖手机等终端、或功能单一,难以兼顾本地存储、多维度操控与交互体验,而基于单片机的嵌入式设计凭借低成本、易实现、可拓展的特性,成为解决这一问题的理想方案,契合小型化智能音频设备的发展趋势。

从现实使用需求来看,普通用户对音乐播放器的诉求已从单纯听音延伸至多场景适配:既需要摆脱网络依赖,通过外置SD卡实现海量音乐本地存储与自动播放;也希望通过独立按键直观完成开关机、曲目切换、音量/播放速度调节及灯光控制等操作;七彩灯光与音乐播放的视觉联动,能提升使用的沉浸感。此外,蓝牙远程控制的需求日益凸显,可突破物理按键的空间限制,适配居家、户外等场景,符合智能设备“无线化、便捷化”的发展方向。

1.1.2  选题意义

当前手机虽为主流听音工具,但存在显著适配短板:手机需承载软件安装、照片存储等多元功能,内存资源被大量占用,多数用户不愿为音乐文件预留存储空间;且手机体积偏大,便携性受限,在线听歌还需支付会员费用,难以满足纯粹的听音需求。在此背景下,研制小型化、聚焦核心听歌需求的播放器具有重要现实意义。

本设计基于单片机开发,以 SD 卡外置存储解决音乐存储依赖手机内存的问题,存储容量灵活且不占用终端资源;独立按键与蓝牙远程双操控模式,可便捷实现开关机、曲目切换等核心操作,适配不同使用场景;七彩灯光与音乐联动提升听音体验,音量、播放速度调节则贴合个性化需求。

该设计以低成本实现功能集成,既填补了手机听音的场景空白,满足用户对轻量化、低成本纯音乐播放设备的需求,也为嵌入式音频设备的小型化、实用化研发提供了可落地的实践方案,具备较强的应用推广价值。

1.2  国内外研究现状

1.2.1  国内研究现状

国内基于单片机的音乐播放器相关研究已形成扎实的技术基础,且聚焦实用化与多功能集成趋势。在主控芯片应用方面,研究已从传统51单片机逐步向性能更优的STM32系列拓展,依托其丰富的外设接口和高效运算能力,实现更复杂的音频控制逻辑。硬件集成层面,现有研究普遍采用“单片机+专用解码模块”的架构,如通过VS1003、YX5200等解码芯片实现MP3、WAV格式文件播放,并搭配SD卡作为外置存储介质,解决本地音乐存储容量受限的问题,契合用户对海量音乐存储的需求。

功能拓展方面,国内研究注重多模块协同,将音频播放与交互控制深度结合。部分设计已实现独立按键控制开关机、曲目切换及音量调节等基础功能,更有研究融入语音控制与灯光联动技术,如智能语音灯光控制系统通过单片机解析语音指令,同步调节灯光状态,为音乐播放器的声光协同提供了技术参考。

该领域研究与教学结合紧密,诸多高校将音乐盒、小型播放器设计作为单片机应用技术的实践案例,推动了技术普及与创新迭代。但现有研究仍存在优化空间,在蓝牙远程控制与按键双控的响应优先级协调、灯光与音乐节奏的精准联动等方面,尚未形成成熟的低成本解决方案,难以充分满足用户对轻量化、高交互性专用播放器的需求。

1.2.2  国外研究现状

国外在单片机音频相关设备的研究起步较早,技术体系更为成熟,核心聚焦低功耗、高可靠性与跨场景适配。在主控芯片选型上,除STM32系列外,ATMega328P、ESP32等单片机的应用较为广泛,研究重点集中在处理器资源调度优化,通过改进中断处理机制和任务分配算法,确保音频播放的实时性与稳定性。硬件设计层面,国外研究强调模块化与低成本集成,普遍采用SPI接口实现单片机与SD卡、音频放大模块的高速通信,搭配LM386、PAM8403等低成本功放芯片,构建轻量化硬件架构,符合便携设备的设计需求。

功能研发方面,国外研究呈现技术融合与智能化趋势。一方面,AI技术逐步渗透到单片机应用中,通过嵌入简易语音识别算法,实现音频播放的智能控制,提升人机交互体验;另一方面,注重多通信方式集成,蓝牙无线传输已成为中高端设计的标配,突破物理操控的空间限制。

国外研究高度重视系统稳定性测试,通过加速老化试验、前驱信号识别等方法,优化单板计算机的长期运行性能,为音乐播放器的可靠性提供保障。但现有研究多偏向工业级应用或通用型多媒体设备,针对民用小型音乐播放器的专项优化不足,尤其在按键与蓝牙双控协同、七彩灯光与音乐节奏的个性化适配等细分场景,针对性解决方案较少,难以满足用户对纯粹听音场景的精准需求。

1.3  研究方法

为实现基于STM32F103C8T6单片机、具备SD卡外置存储、按键+蓝牙双控及音乐联动七彩灯光的轻量化MP3播放器设计,采用硬件模块化设计方法,完成STM32F103C8T6最小系统与MP3模块、SD卡、独立按键、七彩LED灯、蓝牙模块的电路原理图绘制及硬件焊接,配置GPIO口、USART串口和TIM定时器,实现各硬件模块的物理连接与基础电气适配,达到硬件系统稳定供电、信号可正常传输的阶段性目标。

采用分层软件开发方法,移植FatFs文件系统并开发MP3模块驱动程序,编写SD卡音乐文件的读取、索引与自动播放逻辑,同时开发按键中断处理程序和蓝牙通信协议解析程序,映射开关机、切歌等功能指令,达到软件层面可独立解析并执行单一控制指令的阶段性目标。

采用系统调试与优化方法,设计PWM驱动算法实现七彩LED灯与音乐播放的视觉联动,优化按键与蓝牙指令的响应优先级逻辑,通过多场景测试排查并解决指令冲突、播放卡顿等问题,达到播放器全功能稳定运行的最终目标。

1.4  研究方主要内容

第1章绪论:对课题的研究背景进行了简要的阐述,并提出了本次课题的研究课题的现实意义;

第2章系统设计方案:在本文的第1章中,通过对目前国内外以及目前对于音乐播放器的认识,分析了目前设计中存在的不足之处,总结出本设计的作用,并对本次设计中采用的设备进行比较与选取;在此基础上,给出了该方案的总体框图。

第3章硬件设计:针对本次设计中所采用的设备,对其在本文中所达到的作用做了简单的说明,并对设备的特性和可能性作了说明。

第4章系统程序设计:为本项目的软件开发,主要阐述了本项目的主要工作流程和各部分工作过程。

第5章仿真的调试:画出了模拟的流程图,然后模拟和调试了这次的函数,把模拟中出现的问题以及处理办法都做了详细的记载,并对模拟函数的执行情况进行了详细的说明。    

第6章实物的测试:对实际产品进行了焊接和调试,然后对本章的功能进行了试验,通过本章对本章的实际性能进行了检验,并对本章的函数进行了验证;这是一个很好的标志。

第7章结论:对该项目的研究做了一个小结。

 

2  系统设计方案

2.1  主要模块方案选择

2.1.1  主控芯片方案选择

主控芯片是音乐播放器系统的核心,本设计对比STC89C52RC与STM32F103C8T6两款单片机方案,最终选定STM32F103C8T6作为主控芯片。

STC89C52RC为8位单片机,主频最高12MHz,外设仅含少量GPIO口与1路UART串口,无硬件PWM定时器,需软件模拟实现七彩LED灯调光,且运算效率低,难以同时处理SD卡音乐读取、按键中断、蓝牙指令解析等多任务。

而STM32F103C8T6基于32位ARMCortex-M3内核,主频达72MHz,运算能力是STC89C52RC的数十倍;其具备3路硬件TIM定时器(支持PWM输出)、3路USART串口(可同时适配MP3模块与蓝牙模块通信)、SDIO专用接口(高效读取SD卡音乐文件),能满足按键多功能控制、蓝牙指令解析、灯光音乐联动等核心需求。该芯片成本适中,封装紧凑,适配便携式播放器的轻量化设计,因此确定其为系统主控芯片,实物如图1所示。

图1  STM32F103C8T6实物图

2.1.2  按键模块方案选择

按键模块是播放器人机交互的核心,本设计对比矩阵式薄膜按键与轻触式独立按键两种方案,最终选定独立按键作为控制模块。

矩阵式薄膜按键虽能通过行列扫描方式,以少量GPIO口扩展多按键数量,节省主控芯片IO资源,但薄膜材质机械寿命短(约5万次按压),按压反馈模糊,且本设计需实现开关机、曲目切换、播放加减速等6项功能控制,矩阵式布线需额外增加上拉/下拉电阻,焊接与调试复杂度高,户外使用时抗电磁干扰能力弱,易出现按键误触问题。

轻触式独立按键每个按键对应独立GPIO口,直接与STM32F103C8T6的GPIO口相连,电路结构简洁,按压反馈清晰,机械寿命可达10万次以上,抗干扰性强;且STM32F103C8T6富余的GPIO口可完全满足6个功能按键的连接需求,无需额外IO扩展,调试维护便捷,成本仅略高于薄膜按键。综合稳定性、适配性与易用性,确定选用独立按键模块,实物如图2所示。

图2  独立按键实物图

2.1.3  语音识别模块方案选择

本设计对比HX-M02特定人声语音模块与LD3320非特定人声语音识别模块,最终选定后者。

HX-M02需用户提前录入特定指令音,仅适配录入者的语音控制,通用性差;且需外接麦克风与功放元件,硬件电路复杂,与STM32F103C8T6的通信接口兼容性弱,指令配置流程繁琐。

LD3320模块为非特定人声识别,无需提前训练,任意用户均可直接触发指令,适配性更强;其集成了麦克风、功放及接口元件,无需额外外设,硬件集成度高;支持UART串口通信,可直接与STM32F103C8T6的USART串口连接,调试便捷;同时能快速将“播放”“切歌”等指令映射至播放器控制逻辑,契合本设计的语音交互需求。综合通用性、集成度与适配性,选定该LD3320语音识别模块,实物如图3所示。

图3  语音识别实物图

2.2  整体系统框图设计

本系统以单片机最小系统为核心控制枢纽,模块交互逻辑明确:左侧为输入与供电单元,供电模块为整个系统提供稳定电源;语音识别模块、独立按键模块分别向单片机传输语音指令与物理按键指令(如开关机、曲目切换等)。

单片机接收指令后,向右侧输出模块发送控制信号:驱动 MP3 播放模块,该模块对接 SD 卡存储模块,读取其中的音乐文件完成播放;同时控制七彩 LED 灯光模块,实现音乐与灯光的联动视觉效果。系统框图如图4所示。

图4  系统整体框图

2.3  本章小结

本章围绕基于 STM32F103C8T6 的音乐播放器展开系统方案设计,完成核心功能模块的选型与架构搭建。通过对比分析,确定以 STM32F103C8T6 为主控芯片、轻触式独立按键为交互模块,搭配 MP3 播放模块、SD 卡存储模块、七彩 LED 灯光模块及蓝牙模块构建系统。同时绘制系统框图,明确各模块的连接关系与数据流向,阐明单片机作为核心枢纽,接收按键与蓝牙指令,驱动 MP3 模块读取 SD 卡音乐并实现灯光联动的工作逻辑。本章为后续硬件电路设计与软件程序开发奠定了坚实的理论与方案基础。

 

3  系统硬件设计

3.1  单片机最小系统

3.1.1  主控模块电路

STM32F103C8T6 是 ST 公司推出的基于 ARM Cortex-M3 内核的 32 位单片机,属于 STM32F1 系列的高性价比型号,适配便携式嵌入式设备开发。其核心主频达 72MHz,运算性能可支撑多任务并行处理,能同时完成 SD 卡音乐文件读取、按键中断响应、蓝牙指令解析等播放器核心逻辑运算。

该芯片具备 48 引脚 LQFP 封装(体积紧凑适配轻量化设计),外设资源覆盖本设计需求:含 37 个 GPIO 口(满足独立按键、七彩 LED 灯的连接)、3 路 USART 串口(可同时对接 MP3 模块与蓝牙模块)、3 路 TIM 定时器(支持 PWM 信号输出以驱动灯光调光),还配备 SDIO 专用接口(提升 SD 卡音乐读取效率),且成本适中,是本音乐播放器的理想主控核心。其原理图如图5所示。

4  系统软件设计

4.1  编程软件介绍

本设计所用到的编程软件为Keil5,其界面如图12所示:

图12  Keil5开发界面

本文采用Keil5作为开发平台,与其它的开发环境相比,Keil5具有更轻、速度更快、更简便的特点;受到了众多的嵌入式开发人员的青睐。Keil5支援种类繁多的单片机,包括51 MCU,STM32,HC32等;如 NXP等,所产生的 HEX格式,可以用烧录器将其写入 MCU,使用十分便捷。此外,Keil5的编译分为三种类型,分别为一次编译和一次半编译;另一种方法则是将所有内容都进行编辑,让开发者有更多的选项,而所得到的结果也会出现在接口的底部,让开发者能够找到问题所在。

4.2  主程序流程设计

在主要的编程过程中,通过对每个功能的初始化,然后进行 while主循环,在主循环中,将输入的第一个功能为 key功能;这个功能包括两个方面,一是通过对关键字的搜索来获得关键字,二是根据关键字对关键字执行相关的操作,如切换界面、设定阈值等。接下来是一个功能监控功能,这个功能的作用是通过对相关的驱动功能来获得一个测试结果,并且将监控的结果通过蓝牙模块传送到了手机上,使用者还可以在移动电话上发出命令。该装置按照使用者发出的指示,进行相应的操作。然后是第三个功能,这个功能会显示监控的数值和阀值。系统的主流程图如图13所示。

图13  程序总体流程图

4.3  独立按键流程设计

按键设置子流程是播放器本地交互的核心逻辑,负责实现按键指令的稳定识别。流程从“开始”启动,依次完成引脚变量定义、引脚状态初始化;随后判断模式标志位,若为1则置位按键状态标志位。

进入检测环节后,先判断“按键状态标志位为1且引脚低电平”:若不满足,检测引脚是否为高电平,是则置标志位并返回0;若满足,则执行延时消抖(消除按键机械抖动)、复位标志位,最后再次确认引脚低电平后返回对应键值,否则返回0。

此流程通过状态标志位与消抖处理,有效避免按键误触,保障了“暂停/播放”“切歌”等指令的精准识别,为播放器本地操控提供了稳定的逻辑支撑,按键设置子流程图如图14所示。

图14  按键设置子流程图

4.4  本章小结

本章主要探讨了基于单片机的音乐播放器系统的软件设计。首先,在4.1节中介绍了所采用的编程软件,为系统的软件开发提供了基础支持。接着,在4.2节中,详细描述了主程序流程的设计,包括音乐文件的解码与播放、用户交互的处理以及系统状态的管理,确保了系统的整体功能顺利运行。

5  实物测试

5.1  实物整体焊接测试

本设计实物板集成STM32核心板、语音识别模块、SD卡存储模块、独立按键、七彩LED灯及扬声器等元件,焊接测试遵循“先核心后外设”的流程:优先完成STM32核心板的电源、晶振引脚焊接,再依次对接语音模块、MP3模块的串口引脚,以及按键、LED灯的GPIO接口。

测试重点为焊点质量:通过万用表检测电源对地电阻,排除短路风险;逐一检查串口、按键引脚的虚焊、连锡问题,确保模块间通信链路畅通。上电前完成所有焊点核查后,接入USB供电,核心板指示灯正常亮起,各模块无异常发热,初步验证焊接的电气连通性,为后续功能测试提供硬件基础,其界面如图15所示:

图15  整体实物焊接图

5.2  MP3播放实物测试

通过六个按键对MP3播放器的播放功能进行控制是为了提供用户更加便捷的操作体验。以下是每个按键功能的详细描述以及相应的实物测试情况:

5.2.1  K1按键(暂停/播放)

K1按键用于控制音乐的暂停和播放功能。按下K1按键,若音乐正在播放,则暂停播放;若音乐处于暂停状态,则继续播放。这样的设计方便用户在需要时暂停音乐,或者在暂停后继续播放。

暂停实物测试如图16,播放如图17所示,可以看到当用户按下K1按键后,音乐播放器成功地暂停了播放。

图16  停止播放实物测试

图17  启动播放实物测试

5.2.2  K2按键(上一曲)

K2按键用于切换到上一首音乐曲目。用户按下K2按键后,音乐播放器会自动切换到上一首音乐曲目进行播放。

上一曲实物测试如图18所示,当用户按下K2按键时,音乐播放器成功地切换到了上一首音乐曲目。

图18  上一曲播放实物测试

5.2.3  K3按键(下一曲)

下一曲实物测试如图19所示,当用户按下K3按键时,音乐播放器成功地切换到了下一首音乐曲目。

图19  下一曲播放实物测试

5.2.4  K4按键(音量+)

K4按键用于增加音量大小。用户按下K4按键后,音乐播放器会将当前音量调高一个固定的步长。

音量+实物测试如图20所示,当用户按下K4按键时,音乐播放器成功地将音量调高了一个固定的步长。

图20  加音量播放实物测试

5.2.5  K5按键(音量-)

音量-实物测试如图21所示,当用户按下K5按键时,音乐播放器成功地将音量调低了一个固定的步长。

图21  减音量播放实物测试

5.2.6  K6按键(播放模式切换)

K6按键用于切换播放模式,包括单曲循环和全部循环两种模式。在单曲循环模式下,当前音乐曲目会循环播放;在全部循环模式下,所有音乐曲目循环播放。

单曲循环实物测试如图22所示,当用户按下K6按键切换到单曲循环模式时,当前音乐曲目成功地进入了循环播放状态;

图22  单曲循环播放实物测试

附录A:  原理图

附图1 原理图

 

附录B:  PCB板

附图1 原理图

11


 

附录C:  主要源程序

音乐播放器软件的源程序

/**********************************

包含头文件

**********************************/

#include "sys.h"

#include "stdio.h"

#include "string.h"

#include "stdlib.h"

#include "math.h"

#include "delay.h"

#include "gpio.h"

#include "key.h"

#include "oled.h"

#include "usart.h"

#include "mp3.h"

/**********************************

变量定义

**********************************/

uint8_t key_num = 0;                                                                     //按键扫描标志位 

uint8_t flag_display = 0;                                                 //显示界面标志位

uint8_t music_track = 1;                                                 //音乐曲目

uint8_t music_volume = 30;                                           //音乐音量

uint32_t time_num = 0;                                                          //10ms计时

_Bool flag_play = 0;                                                                       //播放启停

_Bool music_mode = 0;                                                                 //播放模式

extern uint8_t usart1_buf[256];                              //串口1接收数组

extern uint8_t usart2_buf[256];                              //串口2接收数组

char display_buf[16];                                                                      //显示数组

/**********************************

函数声明

**********************************/

void Key_function(void);                                                       //按键函数

void Monitor_function(void);                                 //监测函数

void Display_function(void);                                 //显示函数

/****

*******  主函数

*****/

int main(void)

{

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组

        Delay_Init();                                                                                                                              //延时初始化     

        Gpio_Init();                                                                                                                                   //IO初始化

        Key_Init();                                                                                                                                            //按键初始化

        Oled_Init();                                                                                                                                   //OLED初始化

        Oled_Clear_All();                                                                                                                           //清屏

        Usart1_Init(9600);                                                                                                      //串口1初始化

        Usart2_Init(9600);                                                                                                                  //串口2初始化

       

        while(1)

        {

                Key_function();                                                                                                                              //按键函数

                Monitor_function();                                                                                                                //监测函数

                Display_function();                                                                                                         //显示函数

                time_num++;                                                                                                                                          //计时变量+1

                Delay_ms(10);

                if(time_num %10 == 0)

                        LED_SYS = ~LED_SYS;

                if(time_num >= 5000)

                {

                        time_num = 0;

                }

        }

}

/****

*******按键函数

*****/

void Key_function(void)

{

        key_num = Chiclet_Keyboard_Scan(0);                                                //按键扫描

        if(key_num != 0)                                                                                                                            //有按键按下

        {

                switch(key_num)

                {

                        case 1:                                                                                                                 //按键1:启停

                                flag_play = !flag_play;          

                                if(flag_play == 0)

                                        MP3_SendCMD(0x0E,0,0);                                                                   //MP3暂停

                                else                                                         

                                        MP3_SendCMD(0x0D,0,0);                                                                  //MP3播放    

                        break;

                        case 2:                                                                                                                               //按键2:上一曲

                                if(flag_play == 1)

                                {

                                        music_track--;

                                        if(music_track == 0)

                                        {

                                                music_track = MUSIC_NUM;

                                                MP3_SendCMD(0x03, 0, music_track);                         

                                        }

                                        else

                                               MP3_SendCMD(0x02,0,0);

                                }

                        break;

                        case 3:                                                                                                                                                     //按键3:下一曲

                                if(flag_play == 1)

                                {

                                        music_track++;

                                        if(music_track > MUSIC_NUM)

                                        {

                                                music_track = 1;

                                                MP3_SendCMD(0x03, 0, music_track);

                                        }

                                        else

                                        {

                                                MP3_SendCMD(0x01, 0, 0);

                                        }

                                }

                        break;

                       

                        case 4:                                                                                                                                                     //按键4:音量加

                                if(flag_play == 1)

                                {

                                        if(music_volume < 30)

                                        {

                                                music_volume++;

                                                MP3_SendCMD(0x06, 0, music_volume);

                                        }

                                }

                        break;

                       

                        case 5:                                                                                                                                                     //按键5:音量减

                                if(flag_play == 1)

                                {

                                        if(music_volume > 0)

                                        {

                                                music_volume--;

                                                MP3_SendCMD(0x06, 0, music_volume);

                                        }

                                }

                        break;

                       

                        case 6:                                                                                                                                                     //按键6:模式切换

                                if(flag_play == 1)

                                {

                                        music_mode = !music_mode;

                                        if(music_mode == 1)                             

                                                MP3_SendCMD(0x11,0,1);                                                                //循环播放

                                        else

                                                MP3_SendCMD(0x08,0,music_track);                  //单曲播放

                                }

                        break;

                        default:

                               

                        break;

                }

        }

}

/****

*******监测函数

*****/

void Monitor_function(void)

{             

        if(USART1_WaitRecive() == 0)                                                                                                                                                                                                                                                                                                            //如果接收到蓝牙数据

        {

                if(usart1_buf[0] == 0x7E && usart1_buf[1] == 0xFF && usart1_buf[2] == 0x06 && usart1_buf[3] == 0x3D)  //判断接收数据是否正确

                {

                        music_track = usart1_buf[6];                                                                                                                                                                                                                                                                                   //单曲循环模式下接收歌曲播放完成返回值

                        if(music_mode == 1)     

                        {                                             

                                music_track++;                                                                                                                                                                                                                                                                                                                                               //全部循环模式下接收歌曲播放完成返回值加一

                                if(music_track > MUSIC_NUM)                                                                                                                                                                                                                                                                                           //如果大于歌曲总数播放第一首歌

                                {

                                        music_track = 1;                                                                                                            

                                        MP3_SendCMD(0x03, 0, music_track);

                                }

                        }

                }     

                USART1_Clear();

        }     

       

        if(USART2_WaitRecive() == 0)

        {

                switch(usart2_buf[0])

                {

                        case 0x01:                                                                                                               //播放音乐|开始播放

                                flag_play = 1;

                                MP3_SendCMD(0x0D,0,0);

                        break;

                        case 0x02:                                                                                                               //关闭音乐|关闭播放

                                flag_play = 0;

                                MP3_SendCMD(0x0E,0,0);

                        break;

                        case 0x03:                                                                                                               //上一首|播放上一首

                                if(flag_play == 1)

                                {

                                        music_track--;

                                        if(music_track == 0)

                                        {

                                                music_track = MUSIC_NUM;

                                                MP3_SendCMD(0x03, 0, music_track);                         

                                        }

                                        else

                                               MP3_SendCMD(0x02,0,0);

                                }

                        break;

                       

                        case 0x04:                                                                                                               //下一首|播放下一首

                                if(flag_play == 1)

                                {

                                        music_track++;

                                        if(music_track > MUSIC_NUM)

                                        {

                                                music_track = 1;

                                                MP3_SendCMD(0x03, 0, music_track);

                                        }

                                        else

                                        {

                                                MP3_SendCMD(0x01, 0, 0);

                                        }

                                }

                        break;

                        case 0x05:                                                                                                               //音量加

                                if(flag_play == 1)

                                {

                                        if(music_volume < 30)

                                        {

                                                music_volume++;

                                                MP3_SendCMD(0x06, 0, music_volume);

                                        }

                                }

                        break;

                       

                        case 0x06:                                                                                                               //音量减

                                if(flag_play == 1)

                                {

                                        if(music_volume > 0)

                                        {

                                                music_volume--;

                                                MP3_SendCMD(0x06, 0, music_volume);

                                        }

                                }

                        break;

                       

                        case 0x07:                                                                                                               //循环播放

                                if(flag_play == 1)

                                {

                                        music_mode = 1;

                                        MP3_SendCMD(0x11,0,1);  

                                }

                        break;

                        case 0x08:                                                                                                               //单曲播放

                                music_mode = 0;

                                MP3_SendCMD(0x08,0,music_track); 

                        break;

                                       

                        default:

                        break;

                }     

                USART2_Clear();

        }

}

/****

*******显示函数

*****/

void Display_function(void)

{     

        Oled_ShowCHinese(1,0,"曲目:");                                                                                                                       //显示曲目号

        sprintf(display_buf,"%d ",music_track);

        Oled_ShowString(1,6,display_buf);

               

        Oled_ShowCHinese(2,0,"音量:");                                                                                                                       //显示音量大小

        sprintf(display_buf,"%d ",music_volume);

        Oled_ShowString(2,6,display_buf);

       

        Oled_ShowCHinese(3,0,"模式:");                                                                                                                       //显示当前播放模式

        if(music_mode == 1)

                Oled_ShowCHinese(3,3,"循环播放");

        else

                Oled_ShowCHinese(3,3,"单曲循环");

       

        Oled_ShowCHinese(4,0,"状态:");                                                                                                                       //显示当前音乐播放器状态

15

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐