使用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的内容就讲到这了。

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

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

  • 20
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: STM32F1是意法半导体公司推出的一款32位微控制器,具有高性能、低功耗、易开发等特点。而TF,又称微型SD,是一种小型存储介质,十分适用于嵌入式系统中的数据存储。 在STM32F1中,使用TF需要用到SPI或SDIO接口。SPI是一种串行通信协议,可以实现多路设备间的通信。SDIO接口则是一种高速串行接口,可以实现大容量高速数据读写。可以根据需要选择合适的接口。 在使用TF时,需要注意以下几点: 1、引脚设置:需要将TFSTM32F1的接口引脚连接好,通常为SD_CLK、SD_CMD和SD_D0~SD_D3等引脚。 2、初始化:需要进行TF的初始化,包括GPIO和时钟等设置,以及SPI或SDIO接口的初始化。 3、读写操作:可以通过SPI或SDIO接口进行数据的读写操作,需要注意数据格式和时序等问题。 4、错误处理:TF使用过程中可能会出现错误,需要进行相应的错误处理,例如重新初始化或重新读写等操作。 总的来说,STM32F1与TF结合可以实现高效、可靠的数据存储和读写,为嵌入式系统的开发提供了很大的便利。 ### 回答2: STM32F1系列是意法半导体公司推出的一款以ARM Cortex-M3内核为基础的微控制器芯片,具有高性能、低功耗、可靠性强等优良特性,因此被广泛应用于电子设备的嵌入式系统中。而TF则是可携带式存储器的一种,是一种小型、高速存储,常常用于移动设备、汽车配件和行车记录仪等设备中,也称为MicroSD。 在STM32F1嵌入式系统中集成TF,可以很好地实现数据存储和交互功能。STM32F1系列的嵌入式系统具有高度集成、丰富的存储容量和强大的处理功能,可以实现对TF的读写操作。通常情况下,要实现STM32F1的TF功能,需要进行以下几个步骤: 1. 硬件连接:将TF接口与STM32F1芯片的相应IO口连接,同时需要根据TF规格和工作电压选用相应的电平转换电路或电压稳压器。 2. 配置STM32F1芯片的相应外设:在STM32F1芯片中通过SPI或SDIO控制器的外设使芯片支持TF接口的数据读写操作。同时根据芯片的数据处理能力和工作特性,进行相关外设的时钟配置和控制参数的设置。 3. 编写TF驱动程序:通过STM32F1芯片的开发工具和相关资料,编写相应的驱动程序,实现对TF的读取、写入和格式化等功能。 4. 访问TF数据:通过系统中的其他应用程序或文件系统驱动程序,访问TF中的数据,并进行相应的处理和应用,实现音视频播放、数据存储、图像处理等应用。 需要注意的是,TF的读写速度相对慢,因此在数据读写频繁或数据容量较大的情况下,需要进行相应的优化和适当的存储管理,以保证系统的稳定性和性能。此外,在TF使用过程中需要注意数据的保护和备份,以避免数据丢失或数据损坏的情况。 ### 回答3: STM32F1系列MCU是意法半导体公司推出的超低功耗高性能MCU,与传统单片机相比具有处理速度快、存储容量大、低功耗等优点,因此在很多应用中得到了广泛的应用。 TF(T-Flash)是一种小型高容量可插拔式存储,同SD相比体积小、容量大、使用方便等优点,因此被广泛应用于嵌入式系统中的数据存储。 在STM32F1系列MCU中,通过SPI接口可以实现与TF的数据交互。当MCU需要读取或写入TF中的数据时,先通过SPI接口向TF发送控制指令,然后通过SPI接口读取或写入数据。 在使用TF时,需要注意以下几点: 1. 按照TF的电气参数连接TF和MCU的SPI接口。 2. 在读取或写入数据前,需要先对TF进行初始化,并使之进入工作状态。 3. 为了保证数据的完整性,需要对读取和写入的数据进行校验。 4. 为了保证TF的寿命,需要注意TF的读写频率和寿命。 总之,STM32F1系列MCU与TF的结合,可以实现高效、稳定的数据存储和读取操作,使得嵌入式系统在数据处理方面的应用得到了极大的拓展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值