《课程设计(论文)基于FPGA的音乐播放器设计.doc》由会员分享,可在线阅读,更多相关《课程设计(论文)基于FPGA的音乐播放器设计.doc(21页珍藏版)》请在三一办公上搜索。
1、中国地质大学(武汉) 基于FPGA的音乐播放器设计 专 业 班 级 小组成员 指导老师 2015.06目录一、 实现功能2二、 成员及任务分工2三、详细设计及原理31.系统硬件结构设计32.程序流程4四、 具体实现51.SD卡文件系统的初始化52.按键选歌模式63.自动播放模式74.快进、快退、播放/暂停功能75.LCD显示歌曲名及歌词模块86.LED显示功能107.数码管显示当前曲目、总歌曲数和时间功能11五、碰到的问题及解决过程121.问题一122.问题二123. 问题三134. 问题四13六、运行效果13七、设计小结22一、 实现功能 1. 支持SD卡文件读取功能;2. 支持WAV格式音
2、频功能;3. 支持歌词同步显示功能;3. 支持歌曲名称显示功能;4. 支持“播放/暂停”控制功能;5. 支持歌曲选择功能;6. 支持LED灯显示音量功能;7. 支持返回功能;8. 支持硬启动从ROM启动;9.支持数码管显示总歌曲数和第几首歌曲功能;10.支持数码管显示歌曲的播放进度功能;11. 支持LED灯指示拨码开关07状态功能;12. 支持前6首歌曲直接选择功能。 二、 成员及任务分工 姓名所做任务熟悉Nios II 系统开发流程,看懂原工程文件。了解SD卡FAT文件系统大致的读写流程;格式化SD卡为FAT16格式并将.wav和.lrc文件复制到SD卡根目录下。到实验室去测试原工程文件的硬
3、件设置和软件功能。测试软件功能,明确各个按键对应的功能。一起讨论如何更改原来的功能,并添加新功能。完成实验任务,分工书写课程设计报告。 三、详细设计及原理1.系统硬件结构设计本设计采用DE2 开发板,充分利用NiosII 软核的特性,结合自定义用户组件、自定义用户外设。在FPGA 中使用软核处理器的优势在于灵活高效,硬核实现没有灵活性,通常无法使用最新的技术。而应用Nios II 软核处理器,开发者能够完全定制CPU 和外设,获得恰好满足需求的处理器,充分利用了Nios II 处理器灵活和高效的特性。通过DE2 开发板上的SD 卡插槽,读取SD 卡上的音频数据后,送到音频编/解码器,对音质进行
4、相关处理后输出,进行音乐的播放 SD 卡音乐播放是由NiosII 处理器通过软件完成的。该音乐播放器主要分两种播放模式: 按键选歌模式和自动播放模式。根据系统所划分的功能,处理器、音频设备、存储器、输入、输出和交互接口都必须选用硬件设备实现。其中硬件部分如处理器用Altera公司的Nios II软核来实现,MP3音乐文件存储于外部的SD卡中,DE2开发板上有4个为用户预留的按钮可以用来输入,作为MP3播放器的功能键,输出可以使用开发板上的输出口来接音频设备,用户与开发板的交互可以使用开发板上RS-232串行口和JTAG口。整个系统分为四个部分:CPU模块(包括外围配置芯片、扩展芯片等)、存储器
5、(SD卡)模块、LCD显示模块、GPIO接口模块。 图1 mp3播放器硬件整体框图2.程序流程 图2 程序流程图 对于MP3播放器来说,它应该在板子加电时自动加载到SRAM,然后到一个约定的地方读取音乐数据就可以了。 本系统会播放几个音乐文件,所以MP3播放器就需要通过一个机制来管理或定位这些音乐文件,也就是通过一个文件系统管理功能的程序,让这个文件系统软件和MP3播放器配合使用。 音乐文件的存放应该配合MP3音乐的播放,音乐文件的播放和显示通过文件系统获得相应的播放音乐文件的地址和相关信息,存储也应该符合系统文件的定义来存放。也就是说文件系统是存放音乐和播放音乐的一个中间层,是音乐文件播放和
6、音乐文件存放的一个默认标准,所以文件系统的结构定义是文件读取和存储的关键。四、 具体实现1.SD卡文件系统的初始化 调用函数SD_card_init();(1)SD卡简介及FAT16文件系统构成介绍:SD卡(Secure Digital Memory Card)是一种基于半导体快闪记忆器的新一代记忆设备,不需要额外的电源来保持其上记忆的信息。而且它是一体化固体介质,没有任何移动部分,所以不用担心机械运动的损坏。SD卡的结构能保证数字文件传送的安全性,也很容易重新格式化,所以有着广泛的应用领域,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。(2)FAT16文
7、件系统构成 MBR区装有用于启动系统的代码和有关文件系统的重要信息; 在主引导扇区的末尾处含有分区表,分区表用于标识每个分区开始和结束的表项,最多可以有4个分区, 每个分区可以包含不同的文件系统。分区引导扇区记录各个分区启动的引导程序。FAT表记录SD存储卡以簇为单位进行记录的存储空间的信息,簇的大小根据实际系统的电子盘特性设定。根目录区记录文件名和目录名。 用户数据区用于存放用户数据及子目录。 SD卡格式化时,系统采用了FAT16文件格式。主引导区位于整个SD卡的0柱面0磁头,1扇区存放引导程序用于启动和引导操作系统,同时存放SD卡的主分区表,记录卡的分区信息。在总共512字节的主引导记录中
8、,MBR 的引导程序占了其中的446个字节(相对于扇区首地址的偏移量0H1BDH),随后的64字节(偏移量1BEH1FDH)为DPT(Disk Partition Table,硬盘分区表),最后的两个字节“55 AA”(偏移量1FEH1FFH)是分区有效的结束标志。FAT16文件系统最多支持4个分区项,对应于4个分区表。在DPT部分共64字节中,以16字节为分区表项单位描述一个分区的属性。在本系统能够SD卡只作为一种存储介质使用,且整个系统作为一个分区处理。2.按键选歌模式(1) 进入按键选歌 当swit0为0,即无拨码开关置为1时,LCD提示“Press key3 to choose a s
9、ong”,按下KEY3 后,LCD先显示歌曲总数和歌词总数,继而显示当前所选歌名。 LCD_Init(); LCD_Show_Text(title0); lcd_write_cmd(LCD_16207_0_BASE,0xC0); LCD_Show_Text(title1); while(1)/检测进入选歌界面 key=IORD(BUTTON_PIO_BASE,0); key3=key&0x08; if(key3) break; (2)歌曲选择功能上一首 / 下一首功能分别由按键KEY2和按键KEY1实现,播放至最后一首歌时按KEY1按键则将播放第一首歌曲;直接选歌功能由拨码开关SW1015实现
10、,可选择第16首歌曲。a代表当前为第几首歌,num_music为歌曲总数。 key=IORD(BUTTON_PIO_BASE,0); key=key&0x0e; key3=key&0x08; key2=key&0x04; key1=key&0x02; swit2=IORD(SWITCH_PIO_BASE,0); swit2=swit2&0xfc00; switch(swit2) case 0x0400: a=0; break; case 0x0800: a=1; break; case 0x1000: a=2; break; case 0x2000: a=3; break; case 0x40
11、00: a=4; break; case 0x8000: a=5; break; default: if(key1)a=(a+1)%num_music; else if(key2)a=(a+num_music-1)%num_music; break; 后一首 a=(a+1)%num_music; 前一首 a=(a+num_music-1)%num_music;(3) 确认选歌按下KEY3按键,确认当前所选歌曲,开始播放音乐。 if(key3) break;3.自动播放模式(1) 循环播放模式 else if(swi0)/连续播放 a=(a+1)%num_music; time(0,a+1,nu
12、m_music);当开关swi0拨动到1位置时,为循环播放模式,播放下一首歌曲。(2) 单曲循环模式 else if(swi1)/循环播放 a+=0; time(0,a+1,num_music); /显示时间 当开关swi1拨动到1位置时,为单曲循环模式,循环播放当前歌曲。(3) 随机播放模式 else if(swi2)/随机播放 a=(num_lyrics+Tmp1+Tmp2+musica.m_name0)%num_music; time(0,a+1,num_music); /显示时间 当开关swi2拨动到1位置时,为随机播放模式,随机播放歌曲。4.快进、快退、播放/暂停功能(1) 快进 i
13、f(swi4)/快进 b=(b+4)%cluster_num; time(b*clupsec_num,a+1,num_music); /显示时间 usleep(20000); continue; 当开关swi4拨动到1位置时,b是第几个簇,执行b=(b+4)%cluster_num实现快进。(2) 快退 else if(swi5)/快退 b=(b+cluster_num-4)%cluster_num; time(b*clupsec_num,a+1,num_music); /显示时间 usleep(20000); continue; 当开关swi5拨动到1位置时,执行b=(b+cluster_n
14、um-4)%cluster_num实现快退。(3)播放/暂停功能由开关swi6实现,实现代码: else if(swi6)/暂停 b=(b+cluster_num-1)%cluster_num; usleep(20000); continue; 当开关swi6拨动到1位置时,执行b=(b+cluster_num-1)%cluster_num,实现暂停。5.LCD显示歌曲名及歌词模块(1)显示歌名选歌定播放歌曲后,歌曲名会显示在LCD上,调用函数: void show_name(char *name) UINT16 i,j,length_temp,length_n;/歌名显示的页面数 LCD_I
15、nit(); length_temp=strlen(name); if(length_temp=32) length_n=1; else length_n=(length_temp-32)/16+1; for(i=0;ilength_n;i+)/歌名显示的页面数,歌名滚动显示 lcd_write_cmd(LCD_16207_0_BASE,0x80);/写第一行 usleep(100); for(j=0;j16;j+) lcd_write_data(LCD_16207_0_BASE,namej+i*16); usleep(100); lcd_write_cmd(LCD_16207_0_BASE,
16、0xC0);/写第二行 usleep(100); for(j=0;j1) usleep(1000000); else usleep(300000); (2)显示歌词歌曲播放时LCD则会显示歌曲的歌词,先读取歌词后显示歌词,调用函数:num_lyrics=read_lyrics(musica.m_name,lyric,&lyrics,num_lyric,&clupsec_num, &data_sect);/读歌词 for(k=0;k=lyrics.timek+2) &(j+j_base=lyrics.timek+38) &(j+j_baselyrics.timek+70) lcd_write_d
17、ata(LCD_16207_0_BASE, lyrics.textk(j+time_base)/2-2); break; 该函数中首先匹配歌曲名字和歌词名字,找到匹配歌词后,读扇区,读入一个簇的歌词。如果歌词时间没有重复,即一句歌词对应一个时间标志的情况,从歌词开始标志开始读,一个扇区的数据读完,读取下一个扇区,读时间,计算歌词的长度是32的多少倍,将歌词补满32的整数倍个;如果歌词时间有重复,即一句歌词对应多个时间标志的情况,有几个时间信息,取出这句歌词对应的所有时间信息,如果一个扇区的数据读完,读取下一个扇区,进行时间转换,转换成这句歌词时间对应的扇区数,计算歌词的长度是32的多少倍,将歌
18、词补满32的整数倍个;重复歌词读取。将读出来的歌词及其时间按时间顺序排序,将读出来的长歌词转换为短歌词,函数返回数值numb1。6.LED显示功能(1)红灯显示音量将送入播放器的电平Buffer的值取出后按比例缩小,使其最大值为16,然后将缩小后的值通过处理后由LED灯显示。Buffer的值越大,表示当前电平值越大,则LED灯点亮的个数越多。 SD_read_lba(Buffer,j,1); i=0; while(i512) if(!IORD(AUDIO_0_BASE,0) Tmp1=(Bufferi+1(16-Tmp2); Tmp2=Tmp2&0xffff; IOWR(LED_RED_BAS
19、E,0,Tmp2);(2)绿灯指示拨码开关状态DE2平台上只有9个绿色的LED灯,所以只能够指示拨码开关swi08的状态,开关状态为“0”,则对应的灯灭;开关状态为“1”,则对应的灯亮。swit1=IORD(SWITCH_PIO_BASE,0);IOWR(LED_GREEN_BASE,0,swit1);7.数码管显示当前曲目、总歌曲数和时间功能DE2开发平台上共8个数码管,1、2两个数码管显示当前曲目,3、4数码管显示歌曲总数,5、6、7、8四个数码管显示当前歌曲的播放时间。数码管显示时调用函数: void time(int j,int n,int num) int tim2,h2,m2,s2
20、,b2; unsigned int display; j=j/375; tim0=j/60; /min tim1=j%60; /s m1=tim0%10; m0=tim0/10; s1=tim1%10; s0=tim1/10; b1=n%10; b0=n/10; h1=num%10; h0=num/10; display = b0*16*16*16*16*16*16*16+b1*16*16*16*16*16*16+h0*16*16*16*16*16+h1*16*16*16*16+m0*16*16*16+m1*16*16+s0*16+s1; IOWR(SEG7_DISPLAY_BASE,0,di
21、splay);该函数的传入参数j是簇中第几个扇区,n为当前播放的歌曲序号,num为歌曲总数。函数中完成根据j计算当前时间,并将歌曲序号、歌曲总数和时间显示到对应数码管上。五、碰到的问题及解决过程1.问题一在原始软件工程上直接编译,出现system_0.ptf的存储路径与NIOS II工程不相符,导致运行时找不到.ptf文件,错误如下所示。 解决方法:熟悉软件开发流程,在软件工程编译时需要用到相对应的硬件平台的配置信息。新建一个NIOS II工程,在添加 SOPC Builder System PTF File 时,添加正确的ptf文件,添加所需的.c和.h文件,再次编译。2.问题二编译工程时,
22、出现gnu_rules.mk和gtf_rules.mk文件不存在的问题,错误如下图所示。解决方法:在网上搜索了一下所遇到的问题,网友给出的回答是软件与电脑操作系统不兼容,于是将软件的兼容模式设置为 Windows 7,再次编译工程,错误消失,编译成功。3. 问题三在修改NIOS II工程时,不了解SD卡的扇区、簇等概念。解决方法:在网上搜索了关于“SD卡中FAT16文件分析”的文章,了解SD卡的FAT16文件系统。每个扇区通常有512个字节,每个簇可以包括2、4、8、16、32或64个扇区,一个簇中只能放置一个文件的内容,因此文件所占用的空间,只能是簇的整数倍,如果文件实际大小小于一簇,它也要
23、占一簇的空间;如果文件实际大小大于一簇,根据逻辑推算,那么该文件就要占两个簇的空间。一个簇只能容纳一个文件占用,即使这个文件只有0字节,也决不允许两个文件或两个以上的文件共用一个簇,不然会造成数据混乱。因此,单片机读SD卡上的文件时是以簇为单位的。4. 问题四SD卡没有格式化为FAT格式,2G的SD显示为3.18G,导致DE2开发平台无法识别SD卡,程序停在SD卡初始化位置。解决方法:将SD卡在电脑上格式为FAT格式,内存大小恢复到2G一下,再插入到DE2开发平台上,SD卡被成功识别,程序运行正确。六、运行效果1、开机界面 2、歌曲选择模式 3、前一首/后一首功能;按KEY2键选择前一首歌,如
24、果当前为第一首,则前一首为最后一首歌。按KEY1键选择下一首歌,如果当前为最后一首,则下一首为第一首歌。按确认键KEY3选择当前歌曲,继而播放当前歌曲。数码管显示当前歌曲为第几首歌、总歌曲数、当前歌曲播放时长;LCD屏显示播放时长及歌词。4、返回功能拨码开关SW17的状态改变后,直接跳到选歌界面。SW1状态为“1”时,拨码开关SW17的状态改变后,直接跳到循环播放模式。SW2状态为“1”时,拨码开关SW17的状态改变后,直接跳到单曲循环模式。SW3状态为“1”时,拨码开关SW17的状态改变后,直接跳到随机播放模式。5直接选歌功能拨动拨码开关SW1015,直接选择歌曲16。七、设计小结 本次课程
25、设计完成了以下工作:1. 研究了软硬件协同技术,具体研究了软硬件的系统描述、软硬件划分等方面的技术。了解Nios II处理器的结构特性,掌握基于Nios II的嵌入式SOPC系统软硬件设计方法。2. 实现SD卡读写歌词和歌曲的驱动程序。3. 将软硬件协同付诸于实践,在Nios II开发板上实现了MP3播放器。 采用软硬件协同设计的思想来进行MP3系统的设计。从系统性能出发,对系统进行了划分,在硬件的设计中参考了软件的需求。在DE2开发板上对系统进行测试,满足要求。本设计采用SOPC(System On Programmable Chip)技术,利用Nios处理器设计音乐播放器的外部设备,包括片
26、外存储器、LED、七段数码管、按键、SD卡、LCD、拨码开关等的驱动电路,利用嵌入式编程技术实现外部设备的初始化、数据的读取和处理、音频文件的输出和LCD上显示歌曲序号和音量的大小显示。本系统支持SD卡文件读取,支持歌名歌词同步显示在LCD上,支持播放/暂停,前一首、后一首、快进快退等功能。通过数码管显示总歌曲数、当前播放第几首歌曲和播放进度,具有拨码开关指示功能,若开关闭合,点亮对应的led灯,前6首歌曲可直接快捷选择,在播放音乐的状态下,直接跳到选歌界面。经过实验测试,该音乐播放器具有很高的稳定性和实用性。在本次学习中,接触到软硬件协同设计过程,对软硬件协同设计方法有了进一步的了解。复习了
27、verilog语言,熟悉集成开发环境,并尝试解决编译时出现的问题。做完前期的学习工作后,我们开始学习老师所给的工程,添加和修改一些功能。首先我们的工作是还原模板的功能,将其下载如DE2开发板并使之正常工作。在原始软件工程上直接编译,出现system_0.ptf的存储路径与NIOS II工程不相符,导致运行时找不到.ptf文件,编译工程时,出现gnu_rules.mk和gtf_rules.mk文件不存在的问题,经过多次的尝试和网上搜索的资料的帮助,成功运行了模板程序。我们解决问题的能力有了进一步提升。在代码编写的过程中,我对一个成规模的工程有了一个更直接的了解,分模块编写的理念更清晰,对文件的储存方式也有了较深入的探索。通过本次课程设计,我们受益颇深。