单片机解密技术

专业单片机解密,IC解密,芯片解密公的公司

可能是电路最简单的MP3播放器(STM32F103RC最小系统)

本文转自数码之家,作者wangyz1997。

最近在使用STM32F4调试一个MP3播放器,使用STM32F411+WM8978,支持WAV、FLAC和MP3格式,因此积累了好多音频方面的代码。有一天突然突发奇想,STM32F411的时钟频率有100MHz,那么能流畅播放MP3的最低频率能到多少呢?经过实测,30M!这个数据可真是震撼到我了,居然这么低的时钟频率即可流畅解码FLAC和MP3,突然觉得用F4做这个MP3有点浪费……(当然还是要做的,毕竟音质好)

       
于是脑洞大开……能不能用F1完成这个播放器呢?并且脑子中诞生了一个大胆的想法——这个播放器最好能做到最简化,让所有有最小系统的人都可以体验到音乐的乐趣。

       
个人使用的音乐播放器是网易云音乐,它上面下载的FLAC文件都是LV8的,解码需要90k左右的内存,F1自然是全系列都不能满足,但是LV2需要的内存和MP3差不多,需要30k多的内存,这样大部分大容量的F103就能满足了。由于懒得每首歌都转换,就没有移植FLAC的解码,其实是很好实现的,并且解码FLAC所需要的MIPS是比MP3小的。

       
由于使用F4芯片里面有独立的音频PLL和全功能的IIS,F1里面的IIS是残废的(除非使用外置时钟,否则时钟误差极大),因此就排除了用外置DAC的想法。突然,我想到大容量的芯片里面有内置的DAC!那么我们能不能就用这个DAC就输出音频呢!

首先查看选型表,我们常见的STM32F103RCT6就能满足我们的需求,看图。


STM32F103RC大容量系列,有48k的内存(据说是和ZET6一样的晶元,说不定能用上64K,但是这里48K已经足够),还有双路DAC,正好两个声道,用它做播放器,岂不是美滋滋。

等等…这个DAC是12位的。我们常见的音频文件都是16位的,这个DAC并不能接受我们常见的音频文件,需要进行一个转换,这也成了浪费我时间最多的步骤。有人可能会问,12位音质会不会很差啊?我可以负责的告诉你,音质绝对说的过去,至少木耳是听不出来和手机明显的差别的。

说完了DAC的位数,好多人可能还会怀疑这个内置DAC的性能问题。经过手册查询,这个DAC输出值从最低到最高需要4us,也就是250KHz,对于音频完全没问题,而且音频也不会出现幅度这么大的数据。并且带一个可配置的输出缓冲器,可以省掉外部的运放,直接驱动一定的负载,真的离极简设计越来越近了。

说干就干。首先将以前移植好的SD卡驱动简单移植,实现了文件的读取以后,就开始移植WAV播放程序。先移植它是因为WAV不需要解码,直接读文件送进去就好。这里需要提一下我程序框架的问题。由于以前已经有成熟的MP3,因此程序都是有一套框架的。基本的就是设置IIS等参数,然后读文件,等待当前缓冲区播放完再继续读取然后解码。因此我的程序中出现一些IIS字眼不要担心……只是直接移植,懒得改了。

音频播放是定时器+DAC+DMA,这个例程ST官方就有提供,我只是简单移植就让DAC双通道输出了正弦波。

定时器部分就是产生一个和音频文件采样率相同的时钟给DAC,让DAC按照这个速度去找DMA取数据,DMA有两个缓冲区,播放一个缓冲区的时候读取和解码另一个缓冲区,这样纯硬件的播放可以保证恒定并且正确的播放速度,并且不需要使用CPU进行数据的搬运。当一个缓冲区播放完以后,产生中断,切换缓冲区,继续读取。下面是DMA和定时器的初始化代码。



接下来就是把缓冲区改成文件了。一到这儿我傻眼了,F4的DMA有双缓冲模式,F1没有…正在我一筹莫展的时候,我发现F1的DMA中断有一个半传输中断,这玩意儿不就和双缓冲一样的东西嘛……只需要取两倍的缓冲区大小,然后使能半传输和传输完成中断,就能实现类似双缓冲的无缝播放的效果。




注意这里的DataRequestFlag一定要加__IO也就是volatile修饰,要不会被优化掉,卡死在while里。
这里的DualSine12Bit就是缓冲区了,根据中断类型返回是缓冲区起始地址还是加上一个缓冲区(也就是后一半)的地址。

有了数据,声音是出来的。但是杂音非常非常大,只能听到一点点音乐。我想起来我是直接把立体声16位的数据送给DAC的双通道左对齐寄存器(DAC->DHR12LD),我原以为这样就能一次传输两个通道的数据并且舍弃掉低4位,但是我错了。查阅资料发现,IIS的16位数据是signed short,也就是有符号位的,并且负数是用补码保存的,然而我们这里的DAC应该工作在中值为2048(一半参考电压,加耦合电容),因此音频数据我们需要稍微处理一下,如下面程序所示,除以16再加2048转换成无符号数。


经过这样处理,音频已经能很好地播放了,并且音质严重超出了我的预期,真的是很不错,并且DAC的驱动力真的很大,我的耳机串了一个1k的电阻,音量才到人耳舒适的范围,加上两个10uF的耦合电容,要是不算最小系统和SD卡模块总共只需要四个元件。由于电阻很大,因此电容很小也能获得很低的相应频率。

为了换歌曲方便,我加了两个按键,分别是上一曲和下一曲,还加了一个10K的双联音频电位器调整音量,自此一个WAV播放器就搞定了。


硬件连接如上图所示,端口可以在程序里修改。SD卡使用SPI2,CS脚是PB12,CLK=PB13,MISO=PB14,MOSI=PB15。
整个播放器只用了8个IO口!要是只用一个下一曲还可以再省一个,最小系统周围一圈IO口显得空空荡荡的……


整体照,一个最小系统加一个SD卡模块+一个自己焊接的小板子



小板子特写,总共两个电阻两个电容一个电位器两个按键和一个耳机座。


最小系统的IO显得空荡荡的……

SD卡模块,治好颈椎病

接下来的MP3解码也就轻而易举了。移植了HELIX库,声音也很轻松的出来了。
最后,我还将MP3解码器移植了一份直接从ROM读取数据的版本,这样就可以方便的做开机语音和语音提示之类的了。程序只占用了40k,ROM还剩下了200K左右,放44.1KHz,16Bit,64KBps的单声道音频可以放半分钟多,足够了。有兴趣的可以用JLINK烧一个不带任何ID3信息的MP3文件到0x08020000也就是128k的地方感受一下开机语音。

惯例上程序,做这个播放器的初衷很简单,就是希望所有有最小系统的人都可以轻松地享受到音乐的乐趣!


 

本文转自数码之家,作者wangyz1997。

链接:

https://pan.baidu.com/s/1s1GTmjnPle6wwYZzYoc62A

 密码:doau


cache
Processed in 0.013629 Second.