用STM32F103做个简易无损音乐播放器,软解FLAC/MP3/WAV|我爱单片机
用单片机做一个音乐播放器,是我两年前的一个梦想(挖的一个大坑)那是我还才刚刚入门玩51不久当时看了版主@hit00 的几个帖子,还有另外几个坛里的帖子http://bbs.mydigit.cn/read.php?tid=193645http://bbs.mydigit.cn/read.php?tid=188161看得心潮澎湃,决心也做一个。因为手上没同款的片子,就用了STC15F408w做主控。可是,尝试了许久,都没弄出来。其中用过PWM输出,也用过电阻网络,还考虑过尝试使用IIS的音频DAC芯片。程序上,还专门花了好一久去啃了FAT文件系统的东西,自己写了一个简易的文件系统,虽然功能简单,但是读取速度够快板子焊了好多个版本,程序前前后后弄了一年多这是之前弄出来的一些东西这是其中一版的板子,自认为是我焊得最好看的一片洞洞板双声道的16位电阻网络然而,事实是残酷的。结果都不能正常的播放,不是毫无声音,就是声音断断续续。结论就是,51太慢了+自己水平太臭了。于是这个梦就被暂时封存了,直到有一天,我又入了另一个大坑——STM32。当我看到STM32的外设里面带有SDIO和IIS时,感觉播放音频这个大坑又能填了。后来我画了自己的第一块PCB,也是自己的第一块STM32开发板,吧SDIO卡槽和音频IIS接口都专门引出来了原帖看这里(精品贴)历时两月从零开始精心自制stm32开发板[url]http://bbs.mydigit.cn/read.php?tid=1578422[/url]电路图使用的IIS音频DAC芯片是一个廉价的CS4344,好像就2-3大洋的样子这板子虽然表面上看着还不错,但是毕竟第一次画板,经验还是缺乏,就拿播放音频所需的功能,就有两个错误第一个时封装没弄对,耳机插口放不进去,只能这样了第二个更坑,sd卡接口画错了只能掰弯引脚曲线救国了然而画好板子之后的半年,也没有去填这个坑,而是主要在学习基础的东西,STM32比51有的东西多太多了,学了很久还是觉得自己知道的很少。一两周,又突然想起曾经的那个梦,找出资料来重新开张。不得不说,stm32真的要强劲不少。借助成熟的FATFS和内部的DMA(可以设置成从内存自动搬运数据到外设),只用了小半天,几乎没费什么力气的,就让音乐流淌出来。同时,使用上在线调试的方法,配合逻辑分析仪,相比于传统的下载看效果的方法,也让错误更容易被找出来。然而,听多了,发现,这歌放起来不对劲啊,怎么快这么多,声调升高,歌声像赶着唱完的一样。仔细研究,才发觉在常见频率44100hz且需要提供MCK的时候,因为单片机分频的问题,实际的频率的是46875hz,偏差了6%,不奇怪才怪。再看cs4344的手册,官方推荐了两个比较“奇葩”的晶振频率,不好买啊于是乎只能在分频系数上做手脚了。经过计算,发觉最接近的办法是主频小超到80mhz,7分频得MCK为11.428mhz(接近推荐的11.2896)256分频后得到音频播放频率为44.6khz,误差缩小到1%,算是勉强可选,可以接受理论分析未实测:如果用gd32,内部hsi,8mhz,用矫正寄存器向下微调到7.91khz附近,再操作,将能得到更精确的频率上逻辑分析仪检测,没错wav播放有了,对STM32来说算是小菜一碟,那一不做二不休,就继续看看其他的音频播放呗。首先盯上的是MP3,毕竟是最常用的音频格式。上网一查果然有前人做过。使用的是 Helix解码库。借鉴前人的成果,再一番移植和调试,mp3也能播放了!(44.1khz 16位,双声道)解码对内存和cpu的占用都不小,内存上大概消耗了45k的样子(103RCT6只有48k,内存占用很紧张)这是播放一帧的耗时这是解码一帧的耗时之间空闲的7ms,可以用来检测按钮,驱动屏幕显示什么的(目前无屏,以后可以有)做到这步,我已经心满意足了。可是在好奇心和好胜心驱使下,又盯上了解码FLAC。事实上解码FLAC这步,废了我好多时间精力找的flac解码库,移植大半天,声音出来了,但是有断断续续的毛病……找了半个星期没找出来,播放层的代码推倒重新写了一遍,问题依旧……解码时间也是小于播放时间的,解码耗时甚至比mp3还短。还以为我移植有问题……tm居然是库里面有问题!!!!!解码用双缓存……结果两个输出赋值接口都只给1缓塞了数据,2缓就全程打酱油,(′д` )…彡…彡修改后,声音也是流畅的流淌出来。经过测试,FLAC解码只能解leave0-leave2压缩等级的文件,再高级的失败的原因是内存不够用了,实测leave3级占用的内存应该需要80k,103系列伤不起。图满了,楼下继续。本来还要做APE解码的,结果试了下,内存不够,大概需要70k左右吧?只好弃疗这三种音频,播放解码的套路,基本都是一样的。1、打开文件,检测是否符合解码条件(格式,码率,位率,采样率什么的)2、malloc读取缓存区,解码缓冲区,两个播放缓冲区(wav播放只需要播放缓冲区)3、读取并解码第一帧4、配置DMA+IIS开始自动传输5、进入解码循环6、循环内先做读取+解码+写入到没有在播放的播放缓冲区7、等待上一缓存器播放完,期间可以检测按键,刷屏8、播放完成,进行切换,返回第六步9、读取错误,播放完毕,按键操作等等,break出循环,关闭DMA,关闭文件,free各种缓存因为DMA是自动搬运的,由IIS触发,所以播放过程完全不需要处理器理会,处理器只管解码就好。代码编译完的大小,有两个警告,无光痛痒的,不要管因为开启了长文件名支持 ,中文支持,用到了cc936.c文件,所以有接近200k的内容(绝大部分RO-data)都是存放了utf和gbk的转换表芯片只能用STM32F103RDT6及以上型号,因为内存需要配置64k目前没有弄屏幕,所以消息全部是串口输出,波特率是115200开机显示相关信息,注意此时是80mhz运行(8mhz晶振)遍历、计数并输出SD卡/音乐目录下的所有音乐(目前没做遍历整个储存卡的程序,只只指定 SD卡/音乐 目录)遍历完成后开始随机播放,随机播放用了开机是读取ADC的16和17通道的值做随机种子,两个通道分别是内温传感器和内部基准播放过程中的截图,不支持的格式和采样率什么的会自动跳过flac按键和灯的定义播放视频,因为没有合适的外放设备,找了个小玩具来充当下了实际上,耳机听起来的是很杠杠的
代码见楼下
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。