STM32之音乐播放器

这篇具有很好参考价值的文章主要介绍了STM32之音乐播放器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32之音乐播放器

1.硬件平台

  • CPU:STM32F103ZE
  • 屏幕:3.5寸TFTLCD屏
  • 音频解码器: VS1053
  • SD卡、外扩Sram

2.示例效果

STM32之音乐播放器
STM32之音乐播放器

3.软件设计

  VS1053b 是单片 Ogg Vorbis/MP3/AAC/WMA/MIDI 音频解码器,及 IMA ADPCM 编码器和用户加载的 OggVorbis 编码器。
  支持: MP3/WMA/OGG/WAV/FLAC/MIDI/AAC 等音频格式的解码,并支持: OGG/WAV 音频格式的录音,支持高低音调节设置, 功能十分强大。
  它包含了一个高性能、有专利的低功耗 DSP 处理器内核VS_DSP4、工作数据存储器、供用户应用程序和任何固化解码器一起运行的 16 KiB 指令 RAM 及 0.5KiB 多的数据 RAM、串行的控制和输入数据接口、最多 8 个可用的通用 I/O 引脚、一个 UART、并有一个优质的可变采样率立体声 ADC(“咪”、“线路”、“线路+咪”或“线路*2”) 和立体声 DAC、和跟随的一个耳机功放及一个公共电压缓冲器。

3.1 硬件接口

STM32之音乐播放器

引脚 GPIO 说明
VS_MISO PA6 主机输入
VS_MOSI PA7 主机输出
VS_SCK PA5 时钟
VS_XCS PF7 命令片选(低电平有效)
VS_XDCS PF6 数据片选(低电平有效)
VS_DREQ PC13 数据请求线(高电平表示可以接收数据)
VS_RST PE6 复位脚(低电平复位)

3.2 VS1053驱动

/**************硬件接口*****************
**VS_MISO -- PA6 主机输入
**VS_MOSI -- PA7 主机输出
**VS_SCK  -- PA5 时钟
**VS_XCS  -- PF7 命令片选(低电平有效)
**VS_XDCS -- PF6 数据片选(低电平有效)
**VS_DREQ -- PC13 数据请求线(高电平表示可以接收数据)
**VS_RST  -- PE6 复位脚(低电平复位)
**
*****************************************/

void VS1053_Init(void)
{
	/*1. 开时钟*/
	RCC->APB2ENR|=1<<2;//PA
	RCC->APB2ENR|=1<<4;//PC
	RCC->APB2ENR|=1<<6;//PE
	RCC->APB2ENR|=1<<7;//PF
	GPIOA->CRL&=0x000FFFFF;
	GPIOA->CRL|=0x38300000;
	
	GPIOF->CRL&=0x00FFFFFF;
	GPIOF->CRL|=0x33000000;
	
	GPIOC->CRH&=0xFF0FFFFF;
	GPIOC->CRH|=0x00800000;
	
	GPIOE->CRL&=0xF0FFFFFF;
	GPIOE->CRL|=0x03000000;
	VS_XCS=1;
	VS_XDCS=1;
	VS1053_RST();
	VS1053_SetVoice(255,255);
	/*2.配置时钟寄存器*/
	VS1053_WriteRegDat(VS1053_CLOCKF,0x9800);
}
/*SPI收发一个字节*/
u8 VS1053_SPI_ReadWriteData(u8 data_tx)
{
	u8 data_rx=0;
	u8 i=0;
	for(i=0;i<8;i++)
	{
		VS_SCK=0;
		if(data_tx&0x80)VS_MOSI=1;
		else VS_MOSI=0;
		VS_SCK=1;
		data_tx<<=1;
		
		data_rx<<=1;
		if(VS_MISO)data_rx|=0x01;
	}
	return data_rx;
}
/********************往寄存器中写入数据******************
**
**形参:u8 addr --地址
**			u16 data  -- 写入的数据
**********************************************************/
void VS1053_WriteRegDat(u8 addr,u16 data)
{
	while(VS_DREQ==0){}//等待数据线空闲
	VS_XDCS=1;//数据片选拉高
	VS_XCS=0;//命令片选拉低
	VS1053_SPI_ReadWriteData(0x02);//写指令
	VS1053_SPI_ReadWriteData(addr);	//寄存器地址
	VS1053_SPI_ReadWriteData(data>>8);
	VS1053_SPI_ReadWriteData(data>>0);//写入数据
	VS_XCS=1;
}
/*******************从寄存器中读取数据*******************/
u16 VS1053_ReadRegDat(u8 addr)
{
	u16 data=0;
	while(VS_DREQ==0){}//等待数据线空闲
	VS_XDCS=1;//数据片选拉高
	VS_XCS=0;//命令片选拉低
	VS1053_SPI_ReadWriteData(0x03);//读指令
	VS1053_SPI_ReadWriteData(addr);	//寄存器地址
	data=VS1053_SPI_ReadWriteData(0xff)<<8;
	data|=VS1053_SPI_ReadWriteData(0xff);
	VS_XCS=1;
	return data;
}
/****************音量调节*****************
**
**形参:u8 vol_l -- 左声道 0~254
**      u8 vol_r -- 右声道 0~254
**每个增量表示0.5db的衰减,值越大,音量越小
**注意:如果设置 VOL 的值为 0xFFFF,将使芯片进入掉电模式。
**右声道是高 8 位 左声道是低 8 位
*******************************************/
void VS1053_SetVoice(u8 vol_l,u8 vol_r)
{
	u16 temp=vol_r<<8|vol_l;
	VS1053_WriteRegDat(VS1053_VOL,temp);
}
/***************VS1053硬件复位**************/
void VS1053_RST(void)
{
	//硬件复位
	VS_RST=0;
	Delay_Ms(20);
	VS_XDCS=1;//取消数据传输
	VS_XCS=1;//取消命令传输
	VS_RST=1;//完成复位
	//软件复位
	while(VS_DREQ==0){}//等待数据线空闲
	VS1053_WriteRegDat(VS1053_MODE,0x0804);//设置为新模式,进行软件复位
	Delay_Ms(2);	
	while(VS_DREQ==0){}//等待数据线空闲,复位完成
}
/****获取解码时间******/
u16 VS1053_Get_Time(void)
{
	u16 time=0;
	time=VS1053_ReadRegDat(VS1053_DECODE_TIME);
	return time;
}
/****清除解码时间******/
void VS1053_Clear_Time(void)
{
	VS1053_WriteRegDat(VS1053_DECODE_TIME,0);
}

3.3 播放音乐,歌词同步,音乐切换

static unsigned char music_lrc[4096];//存放从文件中读取出来的歌词
static unsigned char music_lrc_str[100][50];//存放筛选过后的歌词
static u16 music_time[200];//保存每句歌词时间
u8 buff_music[4096];
/**************播放音乐****************************/
u8 VS1053_PlayOneMusic(const char *music_file,u8 display_lrc)
{
	u16 i=0,time1,time2;
	u32 k=0;
	u16 y=32;
   u8 vol_l=50,vol_r=50;
	FIL fp;
	FRESULT res;
	UINT br;
	u8 key=0;
	res=f_open(&fp,music_file,FA_READ);//只读
	if(res!=FR_OK)
	{
		//printf("%s文件打开失败err:%d\r\n",music_file,res);
		return 1;
	}
   //printf("VS1053复位成功\r\n");
	LCD_ShowStr2(0,16,(u8 *)music_file,WHITE);//显示歌名
   LCD_Refresh();//更新显示
	VS1053_Clear_Time();//清除解码时间
   	/*3.设置音量*/
	VS1053_SetVoice(50,50);
	while(!f_eof(&fp))//判断是否到文件尾
	{
		key=Key_Scan();
		if(key==1)
		{
			break;//切换下一首
		}
      else if(key==2)//声音加
      {
         if(vol_l<250)
         {
            vol_l+=50;
            vol_r+=50;
         }
         VS1053_SetVoice(vol_l,vol_r);
      }
      else if(key==3)//声音减
      {
         if(vol_l>0)
         {
            vol_l-=50;
            vol_r-=50;
         }
         VS1053_SetVoice(vol_l,vol_r);
      }
		if(f_read(&fp,buff_music,sizeof(buff_music),&br)!=FR_OK)//读取音频数据
		{
			//printf("读取文件失败");
			f_close(&fp);
			return 2;
		}
//		printf("读取数据成功\r\n");
		for(i=0;i<br;i++)
		{
			while(VS_DREQ==0){}//等待数据线空闲
			VS_XDCS=0;//片选拉低,开始发送音乐数据
			VS1053_SPI_ReadWriteData(buff_music[i]);
			VS_XDCS=1;
		}
		time1=VS1053_Get_Time();//获取解码时间
		if(time1!=time2)
		{
			time2=time1;
			if(display_lrc==1)//是否显示歌词
			{
				if(time2>=music_time[k])//通过时间判断显示对应歌词
				{
					if(y>=(LCD_HIGHT-48))//换页显示歌词
					{
						y=32;
						LCD_ReflashBack();//重画背景					
						LCD_ShowStr2(0,16,(u8 *)music_file,WHITE);//显示歌名
					}
               LCD_ShowStr2(y,16,music_lrc_str[k],WHITE);//显示当前行
               if(k>=1 && y>=48)
					{
						LCD_ShowStr2(y-16,16,music_lrc_str[k-1],GRAY);//将上一行清为底色
					}
               LCD_Refresh();//更新显示
               y+=16;
               k++;
				}	
			}
		}
	}
	return 0;
}

3.4 歌词解析

/********************歌词解析******************/
u8 Vs1053_GetLrc_Music(const char *musiclrc)
{
	FIL fil;
	FRESULT res;
	UINT br;
	FILINFO fno;
	char *p=NULL;
	char buff[10];
	u32 time=0,i=0,j=0,k=0,cnt=0,count=0;//记录每句歌词的播放起始时间
	/*1.打开文件*/
	res=f_open(&fil,musiclrc,FA_READ);
	if(res!=FR_OK)
	{
		printf("%s文件打开失败\r\n",musiclrc);
		return 1;
	}
	memset(music_lrc,0,sizeof(music_lrc));
	memset(music_lrc_str,0,sizeof(music_lrc_str));
	/*2.读取歌词*/
	res=f_stat (musiclrc, &fno);//获取文件状态
	if(res!=FR_OK)
	{
		printf("文件状态获取失败\r\n");
		return 2;
	}
	//printf("size=%d\r\n",fno.fsize);	
	res=f_read(&fil,music_lrc,fno.fsize,&br);//读取歌词
	if(res!=FR_OK || br!=fno.fsize)
	{
		printf("读取文件失败\r\n");
		return 3;
	}	
	/*歌词解析*/
	j=0;
	k=0;
	p=strstr((char *)music_lrc,"[0");//找到歌词的起始位置
	p++;
	while(p[i]!='\0')
	{
		buff[j]=p[i];
		j++;
		i++;
		if(p[i]==']')
		{
			//[00:00.65]李荣浩 - 年少有为
			time=0;
			if(buff[6]>=7)time+=1;//最后两位时间大于5,总秒数+1
			time+=((buff[0]-'0')*10+(buff[1]-'0'))*60+(buff[3]-'0')*10+(buff[4]-'0');//歌词起始秒数
			j=0;
			music_time[cnt++]=time;
//			printf("time:%d\r\n",music_time[cnt]);
			/*获取歌词*/
			i++;
         //[00:00.65]李荣浩 - 年少有为
			while(p[i]!='[')//保存一句歌词
			{	
				music_lrc_str[count][k++]=p[i++];
				if(p[i]=='\0')break;
			}
         music_lrc_str[count][k++]='\0';//保存一行歌词
			i++;
         k=0;
         count++;//记录第几行
		}
	}
	memset(music_lrc,0,sizeof(music_lrc));
   k=32;
   for(i=0;i<25;i++)
   {
      strcpy((char *)music_lrc,(char *)music_lrc_str[i]);
      LCD_ShowStr2(k,16,music_lrc,GRAY);//显示一屏幕歌词
      k+=16;
   }
   LCD_Refresh();//更新显示
	return 0;
}

3.5 读取音乐文件,查找歌词,播放音乐

/***********音乐播放***************/
u8 Vs1053_play_Music(const char *music_file)
{
	u32 i=0;
	u8 stat=0;
	DIR dp;
	char *p=NULL;
	FILINFO fno;
	FRESULT res;
	char buff1[50];
	char buff2[50];
	res=f_opendir(&dp,music_file);
	if(res!=FR_OK)
	{
		printf("目录打开失败err:%d\r\n",res);
		return 1;
	}	
	printf("目录打卡成功\r\n");
	while(1)
	{
		res=f_readdir(&dp,&fno);
		if(res!=FR_OK || fno.fname[0]==0)
		{
			break;
		}
//		printf("%s\r\n",fno.fname);
		p=strstr(fno.fname,".mp3");//查找文件中的音频文件
		if(p)
		{
			i=0;
			//G.E.M. 邓紫棋 - 我的秘密
			while(1)
			{
				buff1[i]=fno.fname[i];
				if((fno.fname[i]=='.') && (fno.fname[i+1]=='m') &&  (fno.fname[i+2]=='p') &&  (fno.fname[i+3]=='3'))break;
				i++;
			}
			buff1[i]='\0';
			//显示歌名
			LCD_ReflashBack();//重画背景
         LCD_Refresh();//更新显示
			//printf("歌名:%s\r\n",buff1);
			snprintf((char *)buff2,sizeof(buff2),"%s/%s.lrc",music_file,buff1);
			//printf("buff2:%s\r\n",buff2);
			stat=Vs1053_GetLrc_Music(buff2);//歌词解析
			//if(stat==0)printf("获取歌词成功\r\n");
			snprintf((char *)buff2,sizeof(buff2),"%s/%s.mp3",music_file,buff1);
			stat=VS1053_PlayOneMusic(buff2,!stat);//播放音乐
			if(stat==0)
			{
				printf("音乐播放完成\r\n");
			}
			else
			{
				printf("stat=%d\r\n",stat);
			}
		}
	}
	f_closedir(&dp);
	return 0;
}

3.6 主函数:LCD初始化、SD卡挂载

int main()
{
   FRESULT ret;
   FATFS fs;
	Beep_Init();
	Led_Init();
	Key_Init();
	Usartx_Init(USART1,115200,72);
	TIMx_Init(TIM2,72,20*1000);
	W25Q64_Init();//W25Q64初始化
	IIC_Init();//IIC初始化
	NT35310_Init();//LCD初始化
	SRAM_Init();
AA:
   /*挂载磁盘*/
   ret=f_mount(&fs,"",1);
   if(ret==FR_OK)
   {
      printf("磁盘挂载成功\n");
   }
   else 
   {
      printf("请检查SD卡是否插入!!\r\n");
      Delay_Ms(1000);
      goto AA;
   }
   VS1053_Init();
	while(1)
	{
		Vs1053_play_Music("0:/music");
	}
}

4.工程示例

工程示例:https://download.csdn.net/download/weixin_44453694/85117817文章来源地址https://www.toymoban.com/news/detail-407963.html

到了这里,关于STM32之音乐播放器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机毕设 STM32音乐播放器设计与实现(原理图+源码+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月05日
    浏览(48)
  • 基于RT-Thread+STM32F407的蜂鸣器音乐播放器

    本项目为RT-Thread学习项目,参考于RT-Thread官网Demo示例 硬件基于STM32F407ZGT6正点原子探索者开发板+无源蜂鸣器模块 RTOS软件基于RT-Thread 4.0.5版本 编译器为官方的提供的RT-Thread Studio 会使用到STM32CubeMX 配置产生PWM波 会使用MobaXterm串口终端软件查看串口终端数据 官网Demo示例网址:

    2024年02月02日
    浏览(42)
  • 通信工程毕设 Stm32单片机的音乐播放器设计 - 物联网 嵌入式

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月19日
    浏览(53)
  • 【单片机毕设选题】Stm32单片机的音乐播放器设计 - 物联网 嵌入式

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月20日
    浏览(48)
  • 基于FPGA的音乐播放器硬件电路设计

    基于FPGA的音乐播放器硬件电路设计 随着嵌入式系统技术的不断发展,音乐播放器作为一种便携式设备得到了广泛的应用。本文将介绍一种基于FPGA(Field Programmable Gate Array)的音乐播放器硬件电路设计方案,该方案可以实现高质量的音频播放和文件存储功能。 系统概述 基于

    2024年02月02日
    浏览(64)
  • 【正点原子STM32连载】 第五十四章 音乐播放器实验摘自【正点原子】STM32F103 战舰开发指南V1.2

    1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html# 正点原子战舰STM32F103板载了VS1053B这颗高性能音频编解码芯片,该芯片可以支持wav/mp3/wma/flac/ogg/midi

    2024年02月03日
    浏览(57)
  • 82、基于stm32单片机音乐喷泉设计播放器频谱彩灯系统设计(程序+原理图+参考论文+开题报告+任务书+设计资料+元器件清单等)

    随着人们生活水平的提高和建立绿色城市的向往,音乐喷泉以其独特的魅力和特殊的功能,愈来愈成为休闲娱乐产业中的一项重要产品,音乐喷泉的兴建也越来越多。 根据目前音乐喷泉的发展现状,介绍了一个以STM32单片机为核心的小型音乐喷泉控制系统。给出了一个简洁的单

    2024年02月12日
    浏览(119)
  • 在Winform(C++/CLR)平台设计的(本地&在线)音乐播放器(基于WMP(Windows Media Player)控件实现)

    首先,祝贺阿根廷获得2022世界杯冠军! Winform作为一个比较老的平台,应用其实越来越少了,而即使设计Winform程序,多数人也会选择C#,而不是C++。但是题主在学校学习一门课程被迫使用了Winform/C++,并完成了课程作业,在此分享以下自己的作业,也当作学习纪录。在完成这

    2024年02月09日
    浏览(44)
  • Android 音乐播放器

    ◼ 音乐播放器 . ◼ 要求 : Activity 编程、 ListView 编程、 SeekBar 编程、 ExoPlayer 编程( 播放 、 暂停 、 停止 、 上一首 、 下一首 ),音乐文件放在 assets/music 目录下,界面自拟. ◼ 期望最终效果: ◼ 分别对应 activity_music_list.xml 、 activity_my_music_player.xml 的视图. ◼ 点击列表任

    2024年02月03日
    浏览(55)
  • 开源音乐播放器!

    导读 音乐是生活的一部分。维基百科关于音乐发展历史的文章有这样一段不错的描述说:“全世界所有的人们,包括哪怕是最孤立、与世隔绝的部落,都会有自己的特色音乐……”好吧,我们开源人就构成了一个部落。我建议我们的“音乐形式”应该包括开源音乐播放器。

    2024年02月08日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包