嵌入式课程设计基于RAM音乐播放器的设计与实现解析Word文档下载推荐.docx
《嵌入式课程设计基于RAM音乐播放器的设计与实现解析Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《嵌入式课程设计基于RAM音乐播放器的设计与实现解析Word文档下载推荐.docx(26页珍藏版)》请在冰点文库上搜索。
2.2音乐播放前台功能模块设计
这次的实验我们利用嵌入式开发板的蜂鸣器来制作音乐播放器,使用不同的声音频率来表达我们的do,re,mi,fa,sol,la,si.而LCD界面用来显示音乐播放的相关信息,如图2-2所示。
图2-2
2.3音乐播放实现后台功能模块设计
本设计是以ARM2440芯片板为基础,利用开发板上的蜂鸣器,通过软件编程对蜂鸣器进行发音频率、时间等的控制,进而驱动蜂鸣器来播放音乐。
本设计播放的为编制音乐,即对音乐先进行解码后再播放。
图2-3
3系统硬件平台及接口设计
3.1系统环境
ARM开发板的硬件配置CPU、SDRAM、FLASH、LCD(包括键盘LED驱动器,触摸屏)、以太网、USB、串口、调试接口(JTAG)、AD及扩展。
开发板与主机之间采取JTAG、COM通信。
宿主机在不同平台的搭建:
1)宿主机之windows平台
开发环境:
ADS1.2+超级终端
ADS1.2:
学会使用ADS平台软件,会用AXD进行调试。
超级终端:
一般设置波特率115200,数据位8位,停止位1,无奇偶校验,软件硬件流控制设为无。
2)宿主机之Linux平台
Linux+minicom
Linux:
定制或全部安装。
下载安装交叉编译器
minicom:
初始化,配置,同windows下超级终端。
3.2音乐播放前台模块硬件
音乐播放使用的是蜂鸣器,为了便于调试,设计了蜂鸣器驱动电路,如图3-1所示。
开发板使用的是无源蜂鸣器。
电容用于提高电路抗干扰性能。
电阻起保护三极管的作用,当三极管突然截止时,无源蜂鸣器两端产生的瞬时感应电动势可以通过电阻迅速释放掉,避免叠加到三极管集电极上从而击穿三极管。
图3-1
3.3音乐播放实现后台模块硬件
单片机演奏一个音符,是通过引脚,周期性的输出一个特定频率的方波。
这就需要单片机,在半个周期内输出低电平、另外半个周期输出高电平,周而复始。
演奏时,要根据音符频率的不同,把对应的、半个周期的定时时间初始值,送入定时器,再由定时器按时输出高低电平。
如图3-2所示为音频电路图。
图3-2
3.4系统硬件接口设计
在嵌入式开发板中,蜂鸣器与GPB0口相接。
从系统角度看,嵌入式系统是多种系统要素之间的很多接口的集合,这里罗列的主要资源是系统处理器。
处理器接口可以分成两大类,分别标识为本地总线和硬件总线。
值得注意的是,本文中的总线是根据处理器利用资源时的访问类型单独定义的,与具体的硬件连接没有对应关系。
本地总线是资源与处理器之间的接口总线,它允许无限制的连续访问。
无限制访问意味着处理器能够利用其内部数据类型(如字节、字和双字)访问一个资源的所有要素;
连续访问是指所有资源要素占用的资源地址空间是连续的,中间没有任何间隔。
RAM和EPROM就是与本地总线接口的常见范例。
硬件总线与资源的连接通常有某些限制,如大小、位置、寻址、地址空间或重定位等。
只接受字写入的I/O端口,或者使用前必须先作映射的PCI总线上的外围芯片是硬件总线接口的一些实例。
采用硬件总线连接对软件设计工程师访问资源有一定的限制,可能在软件设计、开发和集成过程中产生复杂代码和代码错误。
4系统软件设计与实现
4.1主程序设计与实现
软件的设计中最重要的是软件的模块化。
模块化是指在解决一个复杂的问题时自顶向下逐层将软件系统划分成若干个模块的过程。
将软件系统划分成多个模块是为了降低软件系统的复杂度,提高可读性,可维护性,但是,模块的划分不是随意的,应该尽量保持其独立性。
每个模块只完成系统要求的独立子功能。
并且与其他的模块的联系最少且接口简单。
尽量做到高内聚低耦合,提高模块的独立性。
本次设计分为蜂鸣器模块,SD卡模块,按键模块。
蜂鸣器模块负责音乐的播放,SD卡模块负责数据的存储,按键模块负责音乐的切换,播放和停止。
这
三个模块联系起来构成了这次设计的音乐播放器的整体。
如图4-1所示主的流程图。
图4-1
4.2键盘扫描程序设计与实现
键盘是电子器件中常见的输入装置。
嵌入式系统中,键盘由一组常开的按键组成。
当按键闭合时就会向嵌入式系统输入一个电平信息。
每个按键都被赋予了一个键码。
嵌入式开发板据此代码执行任务。
按键的行,列线分别连接到按键开关的两端,行线通过上拉电阻接到+5V上。
当无按键按下时,行线处于高电平状态,当有按键按下时行,列线将导通,此时,行线电平将由与此行线相连的列线的电平决定。
这一点是识别矩阵按键是否被按下的关键。
将行线,列线信号配合起来作适当处理,能确定闭合键的位置。
如图4-2所示键盘扫描程序。
图4-2
4.3音乐播放实现后台模块的设计
音乐播放实现后台模块软件编程的主要实现流程如图4-3。
图4-3
5系统软件功能设计
5.1测试的意义和目的
软件测试是程序的一种执行过程,目的是尽可能发现并改正被测试软件中的错误,提高软件的可靠性。
它是软件生命周期中一项非常重要且非常复杂的工作,对软件可靠性保证具有极其重要的意义。
在目前形式化方法和程序正确性证明技术还无望成为实用性方法的情况下,软件测试在将来相当一段时间内仍然是软件可靠性保证的有效方法。
软件工程的总目标是充分利用有限的人力和物力资源,高效率、高质量地完成软件开发项目。
不足的测试势必使软件带着一些未揭露的隐藏错误投入运行,这将意味着更大的危险让用户承担。
过度测试则会浪费许多宝贵的资源。
到测试后期,即使找到了错误,然而付出了过高的代价。
E.W.Dijkstra的一句名言说明了这一道理:
“程序测试只能表明错误的存在,而不能表明错误不存在。
”可见,测试是为了使软件中蕴涵的缺陷低于某一特定值,使产出、投入比达到最大。
5.2测试方案
用户选择自己喜爱的歌曲,将歌曲编制成数字化,烧写进RAM板,在LCD界面查看歌曲播放情况。
5.3系统软件测试
总体软件设计即系统运行过程中的主逻辑,负责整个系统运行过程中各个状态之间的转换,系统初始化完成以后,在音乐模式下,即可通过按键选择音乐目录中的音乐,解码WMA,MP3等格式的音频文件,并播放。
5.4系统硬件测试
通过程序代码烧写软件在将运行好的程序下载到嵌入式开发板之后,我们可以发现嵌入式开发板的蜂鸣器开始响了起来。
唱的是我们事先编入程序的《老鼠爱大米》这首歌。
当然我们也可以通过改变乐谱使蜂鸣器播放出不同的旋律。
在烧写的软件里会打印出蜂鸣器当前播放的音乐的旋律的数据。
如下图5-1。
图5-1
6总结
嵌入式系统具有处理速度快、低功耗、体积小、功能强大且易于移植等优点而得到广泛的应用。
例如MP3(MovingPictureExpertsGroupAudioLayerⅢ)全称是动态影像专家压缩标准音频层面3。
它设计用来大幅度地压缩音频数据量,并实现重放的音质与原来不经压缩的音频相比没有明显的下降。
鉴于MP3编码方式的特点,将其作为音乐播放器的音频文件时,可以在有限的存储空间内存放更多的音频信息。
现在的数字音乐播放器市场,采用ARM主控+DSP音频解码芯片+SD存储卡所构成的数字音乐播放系统具有强大的播放能力和较好的性价比,在中、高端音频解码领域内有着较强的生命力。
在这次的设计中,我们对项目的要求进行了分析,确定了我们主要的工作,让蜂鸣器发声,唱出我们希望它唱的声音。
在这个过程中,虽然我们让蜂鸣器如预计的那样唱出了歌曲,但是,音调之间的差别有些小,所以音乐听起来有些不太清楚。
在以后的工作中,我们会学习与之相关的知识,以求找到出现这个问题的原因。
使音乐播放器能很好的放出音乐。
由于时间紧迫,这次的音乐播放器还存在着较大的问题,比如说,功能比较单一,没有美观的界面等等问题。
我相信在以后的学习中,随着我们对知识了解的加深,这些问题都将会得到解决。
我们的音乐播放器设计的将会越来越完善。
7实现代码
部分代码:
;
=========================================
NAME:
INIT.S
DESC:
Cstartupcodes
Configurememory,ISR,stacks
InitializeC-variables
GEToption.inc
GETmemcfg.inc
GET2440addr.inc
BIT_SELFREFRESHEQU(1<
<
22)
Pre-definedconstants
USERMODEEQU0x10
FIQMODEEQU0x11
IRQMODEEQU0x12
SVCMODEEQU0x13
ABORTMODEEQU0x17
UNDEFMODEEQU0x1b
MODEMASKEQU0x1f
NOINTEQU0xc0
Thelocationofstacks
UserStackEQU(_STACK_BASEADDRESS-0x3800);
0x33ff4800~
SVCStackEQU(_STACK_BASEADDRESS-0x2800);
0x33ff5800~
UndefStackEQU(_STACK_BASEADDRESS-0x2400);
0x33ff5c00~
AbortStackEQU(_STACK_BASEADDRESS-0x2000);
0x33ff6000~
IRQStackEQU(_STACK_BASEADDRESS-0x1000);
0x33ff7000~
FIQStackEQU(_STACK_BASEADDRESS-0x0);
0x33ff8000~
Checkiftasm.exe(armasm-16...@ADS1.0)isused.
GBLLTHUMBCODE
[{CONFIG}=16
THUMBCODESETL{TRUE}
CODE32
|
THUMBCODESETL{FALSE}
]
MACRO
MOV_PC_LR
[THUMBCODE
bxlr
movpc,lr
]
MEND
MOVEQ_PC_LR
bxeqlr
moveqpc,lr
$HandlerLabelHANDLER$HandleLabel
$HandlerLabel
subsp,sp,#4;
decrementsp(tostorejumpaddress)
stmfdsp!
{r0};
PUSHtheworkregistertostack(lrdoesnotpushbecauseitreturntooriginaladdress)
ldrr0,=$HandleLabel;
loadtheaddressofHandleXXXtor0
ldrr0,[r0];
loadthecontents(serviceroutinestartaddress)ofHandleXXX
strr0,[sp,#4];
storethecontents(ISR)ofHandleXXXtostack
ldmfdsp!
{r0,pc};
POPtheworkregisterandpc(jumptoISR)
IMPORT|Image$$RO$$Base|;
BaseofROMcode
IMPORT|Image$$RO$$Limit|;
EndofROMcode(=startofROMdata)
IMPORT|Image$$RW$$Base|;
BaseofRAMtoinitialise
IMPORT|Image$$ZI$$Base|;
Baseandlimitofarea
IMPORT|Image$$ZI$$Limit|;
tozeroinitialise
IMPORTMMU_SetAsyncBusMode
IMPORTMMU_SetFastBusMode;
IMPORTMain;
Themainentryofmonprogram
IMPORTRdNF2SDRAM;
CopyImagefromNandFlashtoSDRAM
AREAInit,CODE,READONLY
ENTRY
EXPORT__ENTRY
__ENTRY
ResetEntry
;
1)Thecode,whichconvertstoBig-endian,shouldbeinlittleendiancode.
2)ThefollowinglittleendiancodewillbecompiledinBig-Endianmode.
Thecodebyteordershouldbechangedasthememorybuswidth.
3)Thepseudoinstruction,DCDcannotbeusedherebecausethelinkergenerateserror.
ASSERT:
DEF:
ENDIAN_CHANGE
[ENDIAN_CHANGE
ASSERT:
ENTRY_BUS_WIDTH
[ENTRY_BUS_WIDTH=32
bChangeBigEndian;
DCD0xea000007
]
[ENTRY_BUS_WIDTH=16
andeqr14,r7,r0,lsl#20;
DCD0x0007ea00
[ENTRY_BUS_WIDTH=8
streqr0,[r0,-r10,ror#1];
DCD0x070000ea
|
bResetHandler
bHandlerUndef;
handlerforUndefinedmode
bHandlerSWI;
handlerforSWIinterrupt
bHandlerPabort;
handlerforPAbort
bHandlerDabort;
handlerforDAbort
b.;
reserved
bHandlerIRQ;
handlerforIRQinterrupt
bHandlerFIQ;
handlerforFIQinterrupt
@0x20
bEnterPWDN;
Mustbe@0x20.
ChangeBigEndian
@0x24
[ENTRY_BUS_WIDTH=32
DCD0xee110f10;
0xee110f10=>
mrcp15,0,r0,c1,c0,0
DCD0xe3800080;
0xe3800080=>
orrr0,r0,#0x80;
//Big-endian
DCD0xee010f10;
0xee010f10=>
mcrp15,0,r0,c1,c0,0
[ENTRY_BUS_WIDTH=16
DCD0x0f10ee11
DCD0x0080e380
DCD0x0f10ee01
[ENTRY_BUS_WIDTH=8
DCD0x100f11ee
DCD0x800080e3
DCD0x100f01ee
DCD0xffffffff;
swinv0xffffffissimilarwithNOPandrunwellinbothendianmode.
DCD0xffffffff
bResetHandler
HandlerFIQHANDLERHandleFIQ
HandlerIRQHANDLERHandleIRQ
HandlerUndefHANDLERHandleUndef
HandlerSWIHANDLERHandleSWI
HandlerDabortHANDLERHandleDabort
HandlerPabortHANDLERHandlePabort
IsrIRQ
reservedforPC
{r8-r9}
ldrr9,=INTOFFSET
ldrr9,[r9]
ldrr8,=HandleEINT0
addr8,r8,r9,lsl#2
ldrr8,[r8]
strr8,[sp,#8]
{r8-r9,pc}
LTORG
ResetHandler
ldrr0,=WTCON;
watchdogdisable
ldrr1,=0x0
strr1,[r0]
ldrr0,=INTMSK
ldrr1,=0xffffffff;
allinterruptdisable
ldrr0,=INTSUBMSK
ldrr1,=0x7fff;
allsubinterruptdisable
[{FALSE}
;
rGPFDAT=(rGPFDAT&
~(0xf<
4))|((~data&
0xf)<
4);
Led_Display
ldrr0,=GPBCON
ldrr1,=0x155500
strr1,[r0]
ldrr0,=GPBDAT
ldrr1,=0x0
ToreducePLLlocktime,adjusttheLOCKTIMEregister.
ldrr0,=LOCKTIME
ldrr1,=0xffffff
[PLL_ON_START
Addedforconfirmclockdivide.for2440.
SettingvalueFclk:
Hclk:
Pclk
ldrr0,=CLKDIVN
ldrr1,=CLKDIV_VAL;
0=1:
1:
1,1=1:
2,2=1:
2:
2,3=1:
4,4=1:
4:
4,5=1:
8,6=1:
3:
3,7=1:
6.
programhasnotbeencopied,sousethesedirectly
[CLKDIV_VAL>
1;
meansFclk:
Hclkisnot1:
1.
mrcp15,0,r0,c1,c0,0
orrr0,r0,#0xc0000000;
R1_nF:
OR:
R1_iA
mcrp15,0,r0,c1,c0,0
bicr0,r0,#0xc0000000;
R1_iA:
R1_nF
ConfigureUPLL
ldrr0,=UPLLCON
ldrr1,=((U_MDIV<
12)+(U_PDIV<
4)+U_SDIV);
Fin=12.0MHz,UCLK=48MHz
nop;
Caution:
AfterUPLLsetting,atleast7-clocksdelay