4. VS1053模块 您所在的位置:网站首页 esp8266读取SD卡播放音乐 4. VS1053模块

4. VS1053模块

2024-06-27 03:45| 来源: 网络整理| 查看: 265

4.4. 例程介绍¶

本例程采用的硬件SPI,硬件SPI在《SPI基础知识》一文已经介绍,不再赘述,这里主要分析代码框架。

在编写VS1053模块驱动时,也要考虑更改硬件环境的情况。我们把VS1053模块引脚相关的宏定义到”VS1053.h”文件中, 在更改或移植的时候只用改宏定义就可以。

程序中以SPI2作为VS1053的硬件接口在VS1053.h中定义,该头文件中还定义了一些数据结构和VS1053的寄存器,完整内容请参考VS1053的SD卡读歌例程。

VS1053.h¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 //... ... /*定义SPI2作为VS1053的硬件接口*/ #define VS_XCS GPIO_Pin_12 /*定义VS1053的片选管脚*/ #define VS_SCLK GPIO_Pin_13 /*定义VS1053的时钟管脚*/ #define VS_MISO GPIO_Pin_14 /*定义VS1053的MISO管脚*/ #define VS_MOSI GPIO_Pin_15 /*定义VS1053的MOSI管脚*/ #define VS_SPIGPIO_PORT GPIOB /* GPIO端口 */ #define VS_SPIGPIO_CLK CC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define VS_SPI SPI2 #define VS_SPI_CLK RCC_APB1Periph_SPI2 #define VS_XDCS GPIO_Pin_6 /*定义VS1053的片选管脚*/ #define VS_GPIO_XDCS_PORT GPIOE /* GPIO端口 */ #define VS_GPIO_XDCS_CLK RCC_APB2Periph_GPIOE /* GPIO端口时钟 */ #define VS_GPIO_RST_PORT GPIOC /* GPIO端口 */ #define VS_GPIO_RST_CLK RCC_APB2Periph_GPIOC /* GPIO端口时钟 */ #define VS_RST GPIO_Pin_3 /*定义VS1053的RST管脚*/ #define VS_GPIO_DREQ_PORT GPIOE /* GPIO端口 */ #define VS_GPIO_DREQ_CLK RCC_APB2Periph_GPIOE /* GPIO端口时钟 */ #define VS_DREQ GPIO_Pin_3 /*定义VS1053的DREQ管脚*/ //... ...

下面是VS1053的IO口/初始化,这里用到了SPI2,所以需要开启SPI的时钟和相应管脚的时钟。初始化VS1053的DREQ管脚,设置为上拉输入,GPIO时钟为50MHZ, 初始化VS1053的RST管脚,设置为推挽输出,GPIO_Speed如果没有修改的话,任然为上次设置的50MHZ。

VS_SCLK、VS_MISO、VS_MOSI均设置为复用推挽输出,VS_XCS、VS_XDCS设置为推挽输出。

SPI_DirectionSPI设置单向或者双向的数据模式,这里选择SPI设置为双线双向全双工;SPI_Mode是设置SPI工作模式,设置为主SPI;SPI_DataSize是设置数据传输的大小,设置为SPI发送接收8位帧; 设置串行同步时钟的空闲状态为高电平,串行同步时钟的第二个跳变沿(上升或下降)数据被采样;SPI_NSS是NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理,设置为内部NSS信号由SSI控制, SPI_BaudRatePrescaler为定义预分频,波特率预分频值为256;SPI_FirstBit是指定数据传输从MSB位还是LSB位开始,设置为数据传输从MSB位开始,SPI_CRCPolynomial为CRC值计算的多项式;

VS1053.c¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 //初始化VS1053的IO口 void VS_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* 初始化STM32 SPI2接口 */ RCC_APB1PeriphClockCmd(VS_SPI_CLK, ENABLE); /* 初始化SPI时钟及相应管脚时钟 */ RCC_APB2PeriphClockCmd(VS_SPIGPIO_CLK|VS_GPIO_DREQ_CLK|VS_GPIO_RST_CLK|VS_GPIO_XDCS_CLK, ENABLE); /* 初始化VS1053的DREQ管脚 */ GPIO_InitStructure.GPIO_Pin = VS_DREQ; //DREQ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO时钟为50MHZ GPIO_Init(VS_GPIO_DREQ_PORT, &GPIO_InitStructure); /* 定义VS1053的RST管脚 */ GPIO_InitStructure.GPIO_Pin = VS_RST; //PB9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(VS_GPIO_RST_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = VS_SCLK | VS_MISO | VS_MOSI; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用输出 GPIO_Init(VS_SPIGPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = VS_XCS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推免输出 GPIO_Init(VS_SPIGPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = VS_XDCS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推免输出 GPIO_Init(VS_GPIO_XDCS_PORT, &GPIO_InitStructure); /* SPI2 配置 */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号由SSI控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(VS_SPI, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPI寄存器 /* 使能 SPI2 */ SPI_Cmd(VS_SPI, ENABLE); SPI2_ReadWriteByte(0xff);//启动传输 }

下面来看一下main函数,main函数中首先需要初始化一下滴答定时器,方便调用系统延时函数,然后初始化串口、LED、按键,最后再初始化VS1053的IO口, 外设初始化完成之后进行ram 测试并打印结果,再进行正弦测试,测试完成再复位一下模块,在while(1)中循环播放歌曲。

main.c¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42int main(void) { /* 启动系统滴答定时器 SysTick */ SysTick_Init(); /* 初始化串口 */ USART1_Config(); f_mount(&fs,"0:",1); /* 初始化LED */ LED_GPIO_Config(); /* 初始化按键 */ EXTI_Key_Config(); /* 初始化VS1053的IO口 */ VS_Init(); /* 打印测试结果 */ printf("vs1053:%4X\n",VS_Ram_Test()); /* 延时100毫秒 */ Delay_ms(100); /* 正弦测试 */ VS_Sine_Test(); /* 硬复位MP3 */ VS_HD_Reset(); /* 软复位VS10XX */ VS_Soft_Reset(); /* 计算歌曲数量 */ song_list_init(); while(1) { // 测试歌曲放在SD卡根目录下 vs1053_player_song(song_list[song_pt]); printf("MusicPlay End\n"); } }

再来看一下vs1053_player_song中做了些什么,首先用VS_Restart_Play函数进行一次切歌的操作,是为了去掉杂音,然后设置音量,音效、重设解码时间,对音乐文件进行不区分大小写处理, 打开文件成功后将SPI设置到高速模式,将音乐文件不断的读出并进行播放,Restart_Play_flag为按键切歌标志位,按键按下后会在中断中置1,然后推出播放下一曲。

VS1053.c¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 void vs1053_player_song(uint8_t *filepath) { uint16_t i=0; /* 切歌 */ VS_Restart_Play(); /* 设置音量,音效等 */ VS_Set_All(); /* 重设解码时间 */ VS_Reset_DecodeTime(); /* 对音乐文件进行不区分大小写处理 */ if(strstr((const char*)filepath,".flac")||strstr((const char*)filepath,".FLAC")) VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN); /* 打开文件 */ result=f_open(&file,(const TCHAR*)filepath,FA_READ); /* 打开文件成功 */ if(result==0) { /* 将SPI设置到高速模式 */ VS_SPI_SpeedHigh(); while(1) { i=0; /* 将文件中的数据读到buffer中,每次读BUFSIZE个数据 */ result=f_read(&file,buffer,BUFSIZE,(UINT*)&bw); do { /* 发送一次音频数据 */ if(VS_Send_MusicData(buffer+i)==0) { i+=32; /* 判断切歌按键是否按下 */ if(Restart_Play_flag) { /* 切歌 */ VS_Restart_Play(); /* 清除标志位 */ Restart_Play_flag = 0; goto exit; } } }while(i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有