计算机钢琴和音乐发生器.doc_第1页
计算机钢琴和音乐发生器.doc_第2页
计算机钢琴和音乐发生器.doc_第3页
计算机钢琴和音乐发生器.doc_第4页
计算机钢琴和音乐发生器.doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

微机原理课程设计报告院 系: 襄樊学院物理与电子工程学院班 级: 电子信息科学与技术0611班指导老师: 张 静姓 名: 杜 勇 06111028邓 丰 06111025雷 雄 06111026目 录一、课题名称及设计组成员2二、课题内容及要求2三、方案、系统组成框图和工作原理说明21、方案22、系统组成框图23、工作原理2四、程序功能描述及程序流程22、程序功能描述23、程序流程图3五、程序源代码及注释3六、DOS/BIOS功能调用,文件列表清单3七、电路的连接及调试31、电路连接32、调试步骤3八、调试中出现的问题、原因及排除方法3九、收获和体会3十、参考文献429一、课题名称及设计组成员课题名称计算机钢琴和音乐发生器程序设计人姓名学号分工杜 勇06111028按键键值与频率查表设计邓 丰06111025按键扫描处理雷 雄06111026固定频率发声分析报告日期2009年 3 月 2 日二、课题内容及要求1、 计算机钢琴基本功能:I、利用键盘按键“q、w、e、r、t、y、u”实现音调的重低音输入,利用键盘按键“a、s、d、f、g、h、j”实现音调的低音输入,利用键盘按键“z、x、c、v、b、n、m”实现音调的中音输入,利用键盘按键“1、2、3、4、5、6、7”实现音调的重低音输入。II、实现菜单选择以及处理各种功能键的多种中级功能。2、 音乐播放系统控制实现功能: 制作一个菜单,使用菜单条选择功能,让用户选择演奏的乐曲。 用定时器方式演奏画皮之主题曲画心实现音乐演奏。 提示使用ESC键或者ENTER键可以退出当前过程或返回DOS。 实现控制变量可以控制不同的效果以及要求,如播放速度,间隔等。 界面美观,程序结构化程度高,模块结构合理。 设计出相应的音乐取码软件。3、 实验环境16位的汇编语言程序设计有几种工作环境,本实验以及所有程序都是通过MASM5.0编译的,MASM5.0一个汇编语言的编译、连接、调试及运行的集成环境。支持标号的快速定位,编译速度快。三、方案、系统组成框图和工作原理说明1、方案基于PC计算机的时钟晶振为1.1931816MHz,利用电脑里面的蜂鸣器发出声音。各音阶标称频率值:/*-*/音符:1234567(重低音)对应频率(Hz):131147165175196220247(低音)对应频率(Hz):262294330349392440494(中音)对应频率(Hz):523587659698784880988(高音)对应频率(Hz):1046117513181397156817601975/*-*/2、系统组成框图PC机扬声器电路以及相关接口电路如下:PC机扬声器电路以及相关接口电路3、工作原理PC中的定时电路有三个通道,通道3用于发声,通道1用于控制系统内部的时钟。大家都十分清楚用DOS的TIME命令可以观察并修改系统内部的一个时钟,这个时钟之所以能连续运转主要依靠定时器的通道1。通道1的工作方式和通道3一样,但是系统启动时设定其发出一个频率固定为18.2Hz的信号,这个信号直接送到系统中的中断控制器。每一个Hz都产生一个硬件中断,一般称这个硬中断为IRQ0,对应的中断号是08H。也就是说,当计算机启动后,我们的机器看上去十分平静,但实际上CPU非常忙碌。在定时器的控制下每隔55毫秒就要执行一个08H号中断,这个中断的主要工作就是连续地计数。在内存0040H:006CH处有四字节的存储空间专门用于保存计数值,CPU每执行一次08H中断,这四字节的计数值就被加1,不难算出这个计数值每增加1091后时间恰好过了1分钟,每增加65454后时间恰好过了1小时。系统内部的时钟之所以能准确走时,靠得就是08H中断和这四字节的计数值。因此我们要想精确的定时,必须依靠时钟计数值才行。由于PC计算机的时钟晶振为1.1931816MHz,根据频率的公式:f=1/T 则频率周期为T=1/f 定时器的计数器为16位计数器,则最大的计数值为65536,那么其定时时间为:t=65536*T=65536/f=0.0549254(秒) 即:PC定时器每秒可中断18.2065次。四、程序功能描述及程序流程2、程序功能描述程序开始,显示提示信息,对缓存区初始化。按键扫描,接着调用发音子程序在把AL送缓存区,发出与按键相对应频率的声音,从而实现计算机钢琴功能。并不停地对Esc键、Enter键扫描,当Esc键或Enter键按下时,就退出程序。当按下p时,显示播放音乐目录。当按下数字选择键时,播放程序中预设的曲目。当检测到q时,退出到计算机钢琴演奏状态。3、程序流程图开始显示缓存区,变量初始化键盘扫描调用发音子程序是否Esc或Enter键是否p键是否为q键返回DOSYNNYYN播放音乐菜单播放音乐程序键盘扫描是否播放完毕YN五、程序源代码及注释;/*-*/;编译环境:MASM5.0;日期:2009-3-2;时间:8:03;数据段定义data segment;数据定义段assumeds:data;建立数据段寄存器寻址msg_1 db $,0dh,0ah;定义字节msg_2db0dh,0ah,In this OS. you can press below keys to enjoy:$msg_3db0dh,0ah,Super Low:q-w-e-r-t-y-u$msg_4db0dh,0ah, Low:a-s-d-f-g-h-j$msg_5db0dh,0ah, Mid:z-x-c-v-b-n-m$msg_6db0dh,0ah, Hig:1-2-3-4-5-6-7$msg_7 db0dh,0ah,Anytime you can press Esc or Enter to exit.$msg_8db0dh,0ah,Whats more, you can press p to play music!$msg_9db0dh,0ah,Please select the music(press q to exit the main menu):$msg_10db0dh,0ah,1. Huaxin$msg_11db0dh,0ah,2. Jingle bells$msg_12db0dh,0ah,3. Happy birthday to you$msg_13db0dh,0ah,4. Happy new year$msg_21db0dh,0ah, $note_tdw 131,147,165,175,196,220,247;重低音dw 262,294,330,349,392,440,494;低音 dw 523,587,659,698,784,880,988;中音 dw 1046,1175,1318,1397,1568,1760,1975;高音dw0;休止符0;1,2,3,4,5,6,7;从低到高key_tdbq,w,e,r,t,y,u;重低音dba,s,d,f,g,h,j;低音dbz,x,c,v,b,n,m;中音db1,2,3,4,5,6,7;高音db0;休止符0;画心music_n1 db b,c,c,x,z,x,x,b,c db 0,b,c,c,x,z,x,b,n db c,0,b,c,c,x,z,x,z,j db z,x,j,g,h,d,g db h,h,c,x,z,j,j,g,h db g,g,h,h,z,j,h,g db s,d,d,d,g,h,h,j,z,g db z,x,x,c,c,b,c,c,x,z,x db z,j,z,x,j,g,h,d,g db h,h,c,x,z,j,g,h,h,0 db d,d,g,h,h,z,j,h,g,h db h,d,d,d,g,h,h,j,z,g,z db x,x,c,c,b,c,c,x,z db x,z,j,z,x,j,g,h,d,g,h db h,c,x,z,j,g,h,h,b,c db c,x,z,x,x,b,c,c,c,b,c db c,x,z,x,b,n,x,c,c db b,c,c,x,z,x,z,j db z,x,j,g,h,d,g,h,h,c db x,z,j,g,h,h,0music_d1 db 4, 4, 8, 4, 4, 8, 4, 4, 16 db 8, 4, 4, 8, 4, 4, 8, 4, 4 db 16, 8, 4, 4, 8, 4, 4, 8, 4, 4 db 4, 4, 4, 4, 8, 4, 4 db 8, 4, 4, 4, 4, 8, 8, 4 db 4, 4, 8, 4, 4, 4, 4, 8 db 4, 2, 16, 4, 4, 8, 4, 4, 4, 4 db 4, 4, 4, 4, 8, 4, 4, 8, 4, 4, 8 db 4, 4, 4, 4, 4, 4, 8, 4, 4 db 8, 4, 4, 4, 4, 8, 4, 2, 8, 8 db 4, 4, 4, 8, 4, 4, 4, 4, 4, 4 db 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 4 db 4, 4, 4, 16, 4, 4, 8, 4, 4 db 8, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8 db 4, 4, 4, 4, 8, 4, 4, 16, 4, 4 db 8, 4, 4, 8, 4, 4, 4, 4, 8, 4, 4 db 8, 4, 4, 8, 4, 4, 4, 4, 8 db 4, 4, 8, 4, 4, 8, 4, 4 db 4, 4, 4, 4, 8, 4, 4, 8, 4, 4 db 4, 4, 8, 4, 4, 32;铃儿响叮当+生日快乐+新年好music_n2 db g,c,x,z,g,0,g,h,g,c,x,z;铃儿响叮当 db h,0,h,a,h,v,c,x,j,g,b,b,v,x,c,z db g,c,x,z,g,0,g,h,g,c,x,z,h,v,c,x db b,b,b,b,n,b,v,x,z db c,c,c,c,c,c,c,b,z,x,c db v,v,v,v,c,c,c,x,x,z,x,b db c,c,c,c,c,c,c,b,z,x,c db v,v,v,v,c,c,b,b,v,x,z,0 db g,g,h,g,z,j;生日快乐 db g,g,h,g,x,z db g,g,b,c,z,j,h db v,v,c,z,x,z,0 db z,z,z,g,c,c,c,z,z,c,b,b,v,c,x,x,c;新年好 db v,v,c,x,c,z,z,c,x,g,j,x,z,0music_d2 db 4, 4, 4, 4, 8, 4, 2, 2, 4, 4, 4, 4 db 8, 4, 2, 2, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 4 db 4, 4, 4, 4, 8, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4 db 4, 4, 4, 4, 4, 4, 4, 4, 16 db 4, 4, 8, 4, 4, 8, 4, 4, 4, 2, 16 db 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 8, 8 db 4, 4, 8, 4, 4, 8, 4, 4, 4, 2, 16 db 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 16,32 db 4, 4, 8, 8, 8, 16 db 4, 4, 8, 8, 8, 16 db 4, 4, 8, 8, 8, 8, 8 db 4, 4, 8, 8, 8, 16, 32 db 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 16, 4, 4 db 8, 8, 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 32jiepai db ?;节拍变量定义speeddb2;播放速度控制jiangedb1;音符间隔停顿时间dataends;数据定义段结束;/*-*/;/*-*/;代码段定义code segment;代码定义段 assumecs:code;建立代码段寄存器寻址;/*-*/;/*-*/;字符显示show macro str;宏定义,输入参数:字符串str leadx,str;装入str的有效地址 mov ah,09h;调用中断21,09h显示字符串 int 21h endm;宏定义结束;/*-*/;/*-*/;主函数mainprocfar;主函数过程定义mov ax,data;取数据段地址mov ds,ax;装载数据段寄存器ds,使之指向当前数据段showmsg_21showmsg_1;调用宏,显示字符串showmsg_2showmsg_3showmsg_4showmsg_5showmsg_6showmsg_7showmsg_8showmsg_21movbx,0;设定查表数组下标初值;/*-*/;/*-*/;按键扫描key_scan:moval,6mov jiepai,al ;初始化节拍movbx,0000h;初始化指针movah, 00h;利用bios的16号中断,扫描键盘按键int16h;AL中返回按键的ASCII码cmpal, 0dh;判断是否为Enter键jzexit;是回车键就退出cmpal, 1bh;判断是否为Esc键jzexit;是退出键就退出cmpal, p;判断是否为p键jzplay;是p键就play musiclookup:cmpkey_tbx,al;取出对应频率值jenextincbx;指针+1jmplookupnext:shlbx,1;指针2,计算频率表指针movcx,note_tbx;取得对应数组下标值的频率值callbeep;调用固定频率子程序jmpkey_scan;否则继续扫描;/*-*/;/*-*/exit:;退出 mov ah,4ch;调用中断21,4ch退出系统 int 21h;/*-*/;/*-*/;音乐播放菜单play:showmsg_9showmsg_10showmsg_11showmsg_12showmsg_13showmsg_21input:movah, 00h;利用bios的16号中断,扫描键盘按键int16h;AL中返回按键的ASCII码cmpal, q;判断是否为Enter键jzstart;是q键就退到主菜单cmpal, 1;判断是否为数字1jznext6;是1键就播放相对应的歌曲cmpal, 2;判断是否为数字2jznext7;是2键就播放相对应的歌曲jmpinput;否则继续扫描按键next6:callplay_m1next7: callplay_m2start:callmain;/*-*/;/*-*/;音乐播放程序1play_m1procnearnext5:movbx,0next3:moval,music_n1bx;取出music频率值 push ax moval,music_d1bx;取出music节拍 mov jiepai,al pop axcmpal, 0;是否为音乐结束标志符jeinput;是则退出playpushbx;保存bx,bx为music频率指针movbx,0look1:cmpkey_tbx,al;查表取出对应频率值的指针bxjenext1;找到就beepincbx;指针+1andbx,0ffhjmplook1;未找到则继续查找next1:shlbx,1;指针2,计算频率表指针movcx,note_tbx;取得对应数组下标值的频率值cmpcx,0jenext4callbeep;调用固定频率子程序callpause;调用停顿时间popbx;获得music指针incbx;继续取得下一个音符jmpnext3next4:callnobeepcallpause;调用停顿时间popbx;获得music指针incbx;继续取得下一个音符jmpnext3play_m1 endp;/*-*/;/*-*/;音乐播放程序2play_m2 procnearnex5:movbx,0nex3:moval,music_n2bx;取出music频率值 push ax moval,music_d2bx;取出music节拍 mov jiepai,al pop axcmpal, 0;是否为音乐结束标志符jeinput;是则退出playpushbx;保存bx,bx为music频率指针movbx,0loo1:cmpkey_tbx,al;查表取出对应频率值的指针bxjenex1;找到就beepincbx;指针+1andbx,0ffhjmploo1;未找到则继续查找nex1:shlbx,1;指针2,计算频率表指针movcx,note_tbx;取得对应数组下标值的频率值cmpcx,0jenex4callbeep;调用固定频率子程序callpause;调用停顿时间popbx;获得music指针incbx;继续取得下一个音符jmpnex3nex4:callnobeepcallpause;调用停顿时间popbx;获得music指针incbx;继续取得下一个音符jmpnex3play_m2 endp;/*-*/;/*-*/mainendp;主函数过程结束;/*-*/;/*-*/;固定频率响beep procnearmovdx,0012hmovax,34dchdivcx;ax为所得分频值out42h,al;输出频率值,低8位moval,ahout42h,al;输出频率值,高8位callspk_on;开启蜂鸣器movah,00h;取时钟计数值int1ahmoval,jiepai;18.2次为1000ms, 2次约为100msaddal,speedcbw ;al值转为16位axaddax,dx;加上当前时钟计数值,得到计数终值movbx,ax;计数终值置入bxdelay1:movah,00hint1ah;取时钟计数值cmpbx,dx;到终值吗?jnzdelay1;未到,继续延时callspk_off;关闭蜂鸣器retbeep endp;/*-*/;/*-*/;休止符延迟时间nobeep procnearcallspk_off;关闭蜂鸣器movah,00h;取时钟计数值int1ahmoval,jiepai;18.2次为1000ms, 2次约为100msaddal,speedcbw ;al值转为16位axaddax,dx;加上当前时钟计数值,得到计数终值movbx,ax;计数终值置入bxdelay2:movah,00hint1ah;取时钟计数值cmpbx,dx;到终值吗?jnzdelay2;未到,继续延时retnobeep endp;/*-*/;/*-*/;音符间隔停顿时间pause procnearcallspk_off;关闭蜂鸣器movah,00h;取时钟计数值int1ahmoval,jiange;18.2次为1000ms, 2次约为100mscbw ;al值转为16位axaddax,dx;加上当前时钟计数值,得到计数终值movbx,ax;计数终值置入bxdelay3:movah,00hint1ah;取时钟计数值cmpbx,dx;到终值吗?jnzdelay3;未到,继续延时retpause endp;/*-*/;/*-*/;开启蜂鸣器spk_on procnearpushax;保存ax的值inal,61h;获取61h端口的当前值oral,03h;把61h端口低二位置1,即打开蜂鸣器out61h,al;输出数据到61h端口popax;恢复ax的值retspk_on endp;/*-*/;/*-*/;关闭蜂鸣器spk_off procnear pushax;保存ax的值 inal,61h;获取61h端口的当前值 andal,0fch;把61h端口低二位置0,即关闭蜂鸣器 out61h,al;输出数据到61h端口 popax;恢复ax的值 retspk_off endp;/*-*/;/*-*/codeends;代码段结束endmain;主程序结束;/*-*/六、DOS/BIOS功能调用,文件列表清单1、扫描键盘按键功能号:0用途:扫描键盘按键键值参数:AH=0调用:INT 16H返回:AL = 按键的ASCII码2、退出系统,返回DOS功能号:4CH用途:读取时钟计数值参数:AH=4CH调用:INT 21H返回:无3、取得时钟计数值 功能号:0用途:读取时钟计数值参数:AH=0调用:INT 1AH返回:CX = 计数值高16位DX = 计数值低16位AL = 0 表示未过24小时AL 0 表示已过24小时七、电路的连接及调试1、电路连接一般无须连接电路,如果想要听到美妙的音乐效果,可以把电脑里面的蜂鸣器接口用导线引出来,外接一个大的扬声器,效果出人意料,非常好听的。2、调试步骤程序直接运行就可以正常工作,如果想要修改参数或添加新的歌曲,可以参考以下步骤:1)运行ASM_MUSIC.EXE音乐代码提取软件,按照歌谱,直接用鼠标电击一个一个的输入就行了,输入完成后,用鼠标电击END键,即可结束输入,然后复制,粘贴到源文件里面的相应位置;2)保存文档,接着用MASM5.0汇编工具编译生成EXE文件;3)运行所生成的EXE文件即可。程序正常运行截图如下:八、调试中出现的问题、原因及排除方法在编程调试的过程中,遇到了很多麻烦,总结起来有以下几点:问题1:寄存器不够用怎么办?原因:使用了太多的寄存器,AX、BX、CX、DX。解决办法:使用外部变量定义,定义外部变量的方法为:变量名数据类型 ?比如节拍变量定义:jiepai db ?;节拍变量定义问题2:跳转,转移指令跳出的范围太大,编译出现错误怎么办?原因:程序结构过于复杂,庞大。解决办法:使用过程,也就是子程序设计,直接把一个要频繁要用到的函数打包成一个子过程,然后用CALL调用子过程就可以了,这样就可以避免使用跳转和转移指令了。比如开启蜂鸣器子过程:;/*-*/;开启蜂鸣器spk_on procnearpushax;保存ax的值inal,61h;获取61h端口的当前值oral,03h;把61h端口低二位置1,即打开蜂鸣器out61h,al;输出数据到61h端口popax;恢复ax的值retspk_on endp;/*-*/调用子过程如下:callspk_on;关闭蜂鸣器问题3:寄存器的值变幻无常,怎么办?原因:程序结构过于复杂,使用寄存器比较频繁,以及使用了BIOS中断程序,这样会导致其它与之相关寄存器的值的改变。解决办法:堆栈是保护环境的主要工具,一旦用错,后过将很严重,比如我们在调试程序的过程中,遇到过这样的问题:在一个函数的开始,我先用PUSH把所有寄存器入栈了,在函数的执行中,我又把一个寄存器PUSH到栈中保存,却忘记了在执行POP指令之前把它恢复出来!这样就造成了所有的寄存器的值都的生了变化,包括数据和代码段寄存器,这样不出问题才怪呢?!所以,要记住,PUSH了一个变量之后在新的PUSH来临之前如果又有POP别的变量的语句,一定会出问题!解决的办法只有一个,把push和pop对上号。问题4:要显示的字符串过多,但又不想重复写代码,既要美观,又要易读,怎么办?原因:过于频繁的调用中断显示字符串,导致程序过于庞大和复杂,可读性差。解决办法:解决这种问题的最好方法是直接把显示部分写成子过程,但是子过程在传递参数的时候不方便,所以就用宏定义,宏定义可以很方便的传递参数,不仅使得程序美观好看,而且可读性好,程序代码紧凑。例如:先在数据段Data Segment里面定义要显示的字符串:msg_1 db $,0dh,0ah;定义字节msg_2 db0dh,0ah,In this OS. you can press below keys to enjoy:$再在代码段Code Segment里面定义要调用的宏:;/*-*/;字符显示Showmacro str;宏定义,输入参数:字符串str leadx,str;装入str的有效地址 mov ah,09h;调用中断21,09h显示字符串 int 21h endm;宏定义结束;/*-*/要显示字符串就可以直接调用宏了,可以带参数,如下所示:Showmsg_1Showmsg_2问题4:汇编里面怎样进行查表处理?原因:还不够牢固的掌握汇编编程解决办法:汇编里面进行查表处理的我只掌握了一种简单的设计,直接用下标例

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论