IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 使用STM32 和 TF卡、VS1003制作MP3 -> 正文阅读

[嵌入式]使用STM32 和 TF卡、VS1003制作MP3

本节我们来使用stm32、TF卡以及VS1003芯片来制作一台简易的MP3播放器。

VS1003是一个集成的MP3解码芯片,它能自动完成MP3、WMA、WAV、MIDI等格式音频文件的解码。

我们利用stm32的SPI接口,通过必要的初始化配置后,从TF/SD卡中读取MP3文件,发送给VS1003,就能完成声音的输出。

1)硬件设计

VS1003芯片的外围需要搭配晶振、阻容等器件;供电需要2.85V和2.5V;通信接口使用SPI,其他必要的信号除了CS片选外,还需要XDCS(数据片选)、XRESET(复位)、DREQ(状态监测)。

实际上,为了减少硬件制作的工作量,我们可以购买VS1003的电路模块,已经搭配好外围器件,只要供电5V、连接通信接口相关的线即可使用,本文选用的是下图这种:

如果diy能力比较强,可以依据下图自己做板子:

STM32使用的具体型号是STM32F103C8T6。选用这款单片机,它没有SD卡接口,只能通过SPI接口去访问SD/TF卡,这样更具有学习意义。

VS1003模块挂载SPI2接口上,TF卡挂载在SPI1接口上(其实二者挂同一个SPI口上也是可以的,这里主要是因为我在实现时,用的是杜邦线连接,分到两个口上比较好插线)。

SD卡或者TF卡的SPI接口接线定义如下图所示,左边为SD卡,右边为TF卡,我们使用SPI接口,只用连接电源以及SPI的4根线即可:

STM32的引脚如下图分配,PA4用作TF卡的片选,PB3~PB6用作操作VS1003的IO口(各引脚的作用已在命名上区分),串口用于打印状态信息,具体见图:

2)cubemx中的设置

在cubemx中建立工程时,如下图所示:

在SPI1建立时,先将速率设为比较低(因为某些低速的存储卡需要初始化时速率在100k~400k,初始化完后,读取数据时,可以把速率设得比较高):

SPI2建立时,速率设为1~2M左右,以便于操作VS1003时速率足够快:

GPIO设置如下:

打开中间件FATFS,并开启长文件名支持,其他不用改:

将堆栈空间设置得大一些:

这样就设置好了,可以生成keil工程,并在keil中编写代码。

3)keil中的代码编写(TF卡和FATFS文件系统部分)

首先了解SPI接口的TF/SD卡初始化过程。

SPI模式下的初始化操作主要过程有:上电->进入SPI模式(CMD0)->检测当前MCU电压是否符合SD卡的要求(CMD8)->开始初始化(ACMD41)->读取卡类型(CMD58)。

当电压达到SD卡的最小工作电压的后,MCU必须使CS,DI为高电平,输出最少74个时钟脉冲后,才能开始发送第一个命令。

SD卡上电后处于SD Bus模式,使CS保持为0,并且发送CMD0命令,SD卡就会进入到SPI模式。在SPI模式下,命令的CRC校验功能默认是禁止的(CMD8命令除外),但是发送第一个CMD0命令时,SD卡是处于SD Bus模式,该模式下CRC校验功能是启动的,因此第一个CMD0命令必须要有正确的CRC校验。正确的CMD0命令应为:0x40, 0x00, 0x00, 0x00, 0x00, 0x95。

CMD8用于检测SD卡接口电压是否满足要求,该命令的参数包括当前MCU接口的电压范围VHS([11:8]),以及用于检测通信的Check Pattern([7:0])。如果SD卡能满足当前MCU的接口电压,它就会返回VHS和Check Pattern的值。需要注意的是,CMD8的CRC校验值必须正确,假如CRC校验不对,SD卡返回的R1值中的CRC错误位就会置1。正确的CMD8的命令应为:0x48,0x00,0x00,0x01,0xaa,0x87。

ACMD41命令用于开始初始化SD卡及检测其是否完成初始化。该命令的参数HCS([30])表示MCU是否支持SDHC和SDXC,若支持HCS置1,反之置0。如果ACDM41命令返回R1的值为0x01,说明SD卡正在初始化,MCU需要重复发送ACMD41,直到返回值R1为0。

初始化完成后,通过发送CMD58指令读取卡的类型(OCR寄存器的CCS位[30]), CCS为1表示当前卡的类型为SDXC或者SDHC,为0表示卡的类型为SDSC。

还有一些其他的指令,可以参见SD卡的操作说明。

初始化过程的代码较长,这里限于篇幅就不贴了,有兴趣可以在文某关注公众号,留言获取所有的源代码。源码中这部分有详细的注释,在SDdriver.c这个文件中:

接着,看文件系统的使用。

这部分我们使用了cubemx自带的中间件——FATFS,只要移植几个函数即可。

在keil工程中,打开user_diskio.c文件,

先改写初始化和获取状态的两个函数,直接修改为返回OK,如下:

用户读函数,主要是依据参数,将它引导到调用SD_ReadDisk()这个函数:

由于我们制作MP3只用到了读存储卡,所以可以不用实现用户写函数(实际上,FATFS中的很多功能,如果不使用也都可以裁剪掉,如USER_write、USER_ioctl函数都可以不用实现)。

SD_ReadDisk()这个函数,主要实现了按扇区读的操作:

读取单个扇区时,调用SD_sendcmd函数发出读取单个数据块命令CMD17,若存储卡返回响应无错误(返回0),则调用SD_ReceiveData函数等待数据块起始标识符0xFE,然后开始读取数据块和CRC校验。

读取多个扇区时,操作和读取单个数据块的相似,先发送命令CMD18,然后开始等待数据块的起始标识符。需要停止读取操作时,发送CMD12命令,返回响应为0表示存储卡处于忙碌状态,只有返回任何不为0的值后,MCU才能发送下一条命令。

SD_sendcmd和SD_ReceiveData函数主要的代码如下:

这里注意一下crc和校验虽然读取了,但并没有使用它。

以上就是读SD卡数据的实现,也就是与FATFS使用必须的函数都已经实现了。

3)keil中的代码编写(VS1003部分)

VS1003中的代码相对简单一些。

初始化时,只需要完成复位、寄存器配置等操作。

复位即是将复位线拉低一段时间,再恢复。

寄存器的配置,最主要的是进入播放模式、设置时钟、设置音量。VS1003要求SPI时钟在主时钟SCLK/6以下,所以,如果想要使用较高速率的SPI接口,就要设置时钟3倍频;音量这里,高8位和低8位分别表示左右声道的衰减dB数,要设置得合适一些,实测衰减设置得较小时,播放的声音会很不正常。

VS1003初始化的代码如下:

实际上,采样率这里不设置也是可以的,因为mp3文件里已经包含了采样率的数据,这里的设置如果不对,vs1003也能按正确的码率解码出声音。

至于播放MP3的过程,就是从存储卡中读取MP3文件内容,再将其发送给VS1003就可以了。不用关心mp3文件的码率、采样率等参数,因为这些在音频文件中都会记录,发送给VS1003后它能自动识别。

操作的主要过程如下:

包括挂载存储卡、读取磁盘目录、循环查找后缀为“mp3、mid、wma、wav”格式的文件,然后读取文件内容,发送给VS1003。

上图中最后if内部执行的是,找到有后缀符号的文件后,打开文件,每次读取512个字节放在buffer中。

当DREQ为高时(允许发送,表示vs1003至少能接收32个字节数据),发送32个字节给VS1003。

到文件末尾时,再发送2048个0给VS1003,停止发送,关闭文件,具体的代码如下:

执行完后,还需要卸载存储卡:

4)代码测试

把tf卡格式化为FAT32格式,存入MP3文件(最好文件名用英文和数字,文件名短一点),然后就可以上电测试了。

测试结果如下:

由打印信息可见,VS1003的寄存器成功写入,存储卡也初始化成功,并且打开mp3文件成功。

同时,接上耳机,可以听到音乐播放。

在实现过程中遇到的一些不理解的问题,也记录在这里:

a)左右声道设置为一样的衰减时,声音很不正常;而且两个声道的音量大小只受小衰减倍数的一边控制,比如设为0xf030,则两个声道的音量实际是衰减为0x30dB,高位的f0完全没起作用,不知道哪里有问题,有明白的大佬可以指点一下;

b)偶尔会发生音量突变成很大声音,现象和音量衰减为全0一样,而且此时播放速度变慢了,打印寄存器发现除了SPI_MODE正常,其他都被清零了,感觉是硬件哪里有问题。

好了,本节使用stm32的SPI接口,挂载TF卡、VS1003制作MP3的内容就讲到这了。

由于本节内容比较多,代码量比较大,本人的技术水平也有限,有些地方讲的很粗略,算抛砖引玉,有兴趣的可以就某些细节深入研究一下,欢迎留言讨论。

欢迎关注我的公众号,可留言“资料”获取所有电路、源码和参考资料:

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-05 21:53:26  更:2022-02-05 21:54:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:47:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码