Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AB32VG1
RT-Thread
音乐播放器
基于 RT-Thread 和 AB32VG1 实现的音乐播放器
发布于 2021-05-16 00:00:24 浏览:1517
订阅该版
[tocm] # 概括 看到这个板子的硬件配置的时候,就想到了可以拿了做一个音乐播放器的设备,想起了多年前使用过的MP3,目标就是想通过这个板子做一个类似以前的 MP3 的设备,用来听听音乐。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbWmF4tT-1621094499137)(开发文档.assets/image-20210515180655142.png)\]](https://img-blog.csdnimg.cn/20210516000217714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 目前实现的功能如下:打钩的是目前已经实现的,别的是想要实现,但是目前还没有实现的。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OV8iHBSs-1621094351259)(开发文档.assets/image-20210515234134908.png)\]](https://img-blog.csdnimg.cn/20210516000238714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 开发环境 - RT-Thread版本:4.0.3 - IDE:RT-Thread Studio (版本: 2.1.0) - 下载和调试工具:Downloader v1.9.7 (中科蓝迅提供:[下载地址](https://gitee.com/bluetrum/Downloader/blob/main/Downloader_v1.9.7.zip)) - 开发板:**中科蓝讯 AB32VG1开发板** - AB32VG1软件包:1.04 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x48rAFia-1621094351261)(开发文档.assets/image-20210515174250073.png)\]](https://img-blog.csdnimg.cn/20210516000306111.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) # 软硬件底层配置 ### 按键 板子上有三个用户按键,对于 S4 按键,由于 MICR 引脚不能作为输入使用,故使用杜邦线将其连接到PA0。 如下图标注所示:三个按键的按下的操作分别为 up、entry、down。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1dbj4Ti8-1621094351280)(开发文档.assets/image-20210515174112984.png)\]](https://img-blog.csdnimg.cn/20210516000326580.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 不重复造轮子~ 对于按键的检测,使用软件包 multibutton 来实现,该软件包能够很方便的检测多种按键情况。 > MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。 对于该软件的更多功能介绍和如何使用,请查看:[《MultiButton》](http://packages.rt-thread.org/detail.html?package=MultiButton),为了不增加篇幅,我就不赘述了。 如下所示,在 RT-Thread Studio 中的 RT-Thread Settings 中勾选对应的软件包即可。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zg7MTctc-1621094351282)(开发文档.assets/image-20210515175043319.png)\]](https://img-blog.csdnimg.cn/20210516000404976.png) 目前只使用了该软件的按键单击事件、双击事件的检测。 ### OLED12864 模块 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykh5Kf2A-1621094351284)(开发文档.assets/image-20210515180655142.png)\]](https://img-blog.csdnimg.cn/2021051600043529.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 如上图图所示,该OLED12864 模块使用的是 IIC 通信,由于我对 AB32VG1 的硬件 I2C 不熟,所以选择了软件 I2C 来控制屏幕的显示。 本来打算直接使用 u8g2 这个强大的软件包来驱动这块屏幕的,结果发现该软件包占用的空间实在是太大了,这块芯片扛不住,所以放弃了。最终选择采用厂家提供的例程直接修改,其实也就只需要配好对应的 SCL 和 SDA 引脚,很庆幸,很快就改好了。 原理图上,对应连接的引脚如下所示。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FIb1LbVd-1621094351286)(开发文档.assets/image-20210515223219909.png)\]](https://img-blog.csdnimg.cn/20210516000450788.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) ### SD 卡模块 SD卡其实我不太会用,刚开始我以为会花很多时间在上面折腾,但是 RT-thread 针对该开发板提供的软件包就完全实现了 SD 卡的配置,完全不需要我动手,原理图我都没看。 在配置文件上勾选使能 SDCARD 即可,如下: ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ej1aieWL-1621094351287)(开发文档.assets/image-20210515223643256.png)\]](https://img-blog.csdnimg.cn/20210516000516381.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 使能 SDCARD,会同时使能了如下几个组件和服务,这些组合使得 SD 卡能够作为文件系统,方便我们使用统一的接口去读取 SD 卡的内容。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210516000535493.png) ### AUDIO 模块 同样由于软件包足够完善,使得我们不需要考虑太多底层的东西。 如下勾选即可: ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ClWMEhlC-1621094351293)(开发文档.assets/image-20210515224258855.png)\]](https://img-blog.csdnimg.cn/20210516000556363.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 但是如果要播放音乐格式的文件,还需要使用 WavPlayer软件包 ,该软件包配合 AUDIO 驱动,能够播放 wav 格式的音乐文件。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210516000614414.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 值得说明的是,由于依赖关系,勾选该软件包会同时使能 optparse 软件包。 # 音乐播放器的实现 音乐播放器虽说功能不多,但是不同的状态切换还是蛮多的,所以理所当然会想到使用状态机的方式实现。 目前实现的状态主要包括如下几个,同时,该树状图也表明了状态间的转移关系。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WF215G2F-1621094351295)(开发文档.assets/image-20210515225601193.png)\]](https://img-blog.csdnimg.cn/20210516000639823.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) ### 状态机的实现 网上关于状态机的实现有很多方法,我看了好多文章都是直接一个状态对应一个动作函数,但是应用在音乐播放器上会有点问题,因为如果你一个状态对应一个函数的话,如果你的音乐歌曲有几百首,那岂不是有几百个函数,所以我对一般的状态机做了点改进,由于没看过别人 MP3 的实现代码,所以不知道是否会有更好的方法来实现,目前只能将就使用了。 如下代码所示,主要是状态转移表的实现,该表给出了所有状态对应的情况,以及状态转移的跳转位置。 ```c typedef struct { uint8_t coordinate; //当前状态索引号 uint8_t back; //返回(双击确定键) void (*enter_operation)(int8_t*); //当前状态执行的操作 /* 当 entry键按下时 sub_base_addr提供子状态的基地址索引,sub_offset_addr提供偏移量,两者相加, 得到下一个状态 */ uint8_t sub_base_addr; //子状态基地址 uint8_t sub_offset_addr; //子状态偏移地址 (用于记录下一步要跳转到的子状态) uint8_t leaf_node_flag; //标志是否为叶子节点(最底层的状态),方便在该状态下按确定可以实现返回功能 } Menu_table; Menu_table table[]= { //索引 - back - function(当前) - 子状态基地址(固定) - 子状态偏移地址 - 标志是否为叶子节点 { 0, 0, (*load_menu), 1, 0, 0}, //0加载界面 { 1, 1, (*main_menu), 2, 0, 0}, //1主菜单界面 { 2, 1, (*playlists), 4, 0, 0}, //歌单 { 3, 1, (*settings_list), 5, 0, 0}, //设置 //播放的子菜单 { 4, 2, (*music_play), 0, 0, 0}, //音乐播放控制: //设置菜单的子菜单 { 5, 3, (*volume_control), 0, 1, 1}, //音量控制 { 6, 3, (*language_setting), 0, 1, 1}, //语言设置 { 7, 3, (*brightness_setting), 0, 1, 1}, //亮度设置 }; ``` 状态转移主要是按键来实现的,每个按键按下,就会触发状态转移,状态转移的代码如下所示: ```c if (rt_event_recv(&sys_event, (BUTTON_PRE_FLAG | BUTTON_ENTRY_FLAG | BUTTON_2ENTRY_FLAG | BUTTON_NEXT_FLAG), RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, &e) == RT_EOK) { //按键 PRE if (rt_event_recv(&sys_event, BUTTON_PRE_FLAG, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, &e) == RT_EOK) { table[func_index].sub_offset_addr -= 1; table[func_index].enter_operation(&table[func_index].sub_offset_addr); } //按键 ENTRY if (rt_event_recv(&sys_event, BUTTON_ENTRY_FLAG, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, &e) == RT_EOK) { if(table[func_index].leaf_node_flag) { func_index = table[func_index].back; //返回上一级菜单位置 table[func_index].enter_operation(&table[func_index].sub_offset_addr); } else if(func_index == 2) //音乐播放则特殊点(所有音乐进入同一个状态) { k = table[func_index].sub_offset_addr; func_index = 4; table[func_index].sub_offset_addr = k; table[func_index].enter_operation(&table[func_index].sub_offset_addr); } else { func_index = table[func_index].sub_base_addr + table[func_index].sub_offset_addr; table[func_index].enter_operation(&table[func_index].sub_offset_addr); } } //按键 ENTRY double click if (rt_event_recv(&sys_event, BUTTON_2ENTRY_FLAG, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, &e) == RT_EOK) { func_index = table[func_index].back; table[func_index].enter_operation(&table[func_index].sub_offset_addr); } //按键 NEXT if (rt_event_recv(&sys_event, BUTTON_NEXT_FLAG, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, &e) == RT_EOK) { table[func_index].sub_offset_addr += 1; table[func_index].enter_operation(&table[func_index].sub_offset_addr); } ``` # 音乐播放展示 首先将音乐文件拷入 SD 卡内的 music 文件,要注意的音乐的格式是 wav 格式,mp3 格式是不支持的,音乐的文件名目前暂时只支持英文字符,别的文件名会显示乱码,建议将就改改,中文的使用拼音呗,将就一下。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210516000706205.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3Njk3MzM1,size_16,color_FFFFFF,t_70) 接着就可以开始愉快的播放音乐了,由于是使用的是耳机,声音录不出来,很尴尬,所以正在找可以接耳机口外放的装备,找到了再补一个视频。话说这个板子播放的音质真滴不错。 下面是录的视频: [bilibili:基于 RT-Thread 和 AB32VG1 实现的音乐播放器](https://www.bilibili.com/video/BV1mf4y1a797/) 这个视频是没有音乐的,因为我手头只有耳机,所以只有自己听了。 买了个能接耳机孔的小音箱,等到了,后面补视频。 代码工程:[MP3_AB32VG1.7z](https://oss-club.rt-thread.org/uploads/20210516/2774aa0dc7a3b628ba8e7d58e60534f4.7z) # 心得体会 使用 RT-Thread 提供的 BSP 真的太方便了,利用RT-Thread现有的软件包,不需要考虑硬件底层就可以开发出比较复杂的功能,真心强大。 由于这段时间比较忙,所以这个 DIY 项目只完成了基本功能,很多扩展功能也没来得及做,后面慢慢补充了。 很高兴能参加这个 DIY 项目,不仅白嫖板子,还能通过这个有趣的项目提高自己的技能。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
Eureka1024
嵌入式软件开发工程师一枚
文章
8
回答
94
被采纳
14
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
正点原子miniSTM32开发板读写sdcard
3
反馈rtt串口驱动对低功耗串口lpuart1不兼容的问题
4
Keil MDK 移植 RT-Thread Nano
5
RT1061/1052 带 RTT + LWIP和LPSPI,有什么坑要注意吗?
6
RT thread HID 如何收发数据
7
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
8
RT-Thread修改项目名称之后不能下载
9
rt-studio编译c++
10
有木有移植rt-thread(nano)到riscv 32位MCU上
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部