收藏 分享(赏)

单片机课程设计报告 电子琴.doc

上传人:精品资料 文档编号:11012446 上传时间:2020-01-31 格式:DOC 页数:24 大小:282.50KB
下载 相关 举报
单片机课程设计报告  电子琴.doc_第1页
第1页 / 共24页
单片机课程设计报告  电子琴.doc_第2页
第2页 / 共24页
单片机课程设计报告  电子琴.doc_第3页
第3页 / 共24页
单片机课程设计报告  电子琴.doc_第4页
第4页 / 共24页
单片机课程设计报告  电子琴.doc_第5页
第5页 / 共24页
点击查看更多>>
资源描述

1、电子音调发生器一、实验目的1. 了解计算机发声原理。 2. 熟悉定时器和键盘扫描电路的工作原理及编程方法。二、实验完成的功能1. 利用键盘 17 进行音调选择,即按下音符产生对应音调。2. 事先存储三首歌曲,并可进行选择播放。3. 谱曲功能:通过按键对 LCD 菜单选项进行选择,进入谱曲界面,通过按键 17 分别输入音高与几分音符类型,由按键输入若干数据完成谱曲。4. 在播放存储歌曲与谱曲播放时,对应音符及其节奏 LCD 显示对应频谱。5. 在播放音乐时按“返回”键出现返回界面,由键盘按“确认”键选择返回主菜单或循环播放。三、实验原理1. 音节由不同频率的方波产生,音节与频率的关系如表(1)所

2、示。要产生音频方波,只要计算出某一音频的周期(1 / 频率) ,然后将此周期除以 2,即为半周期的时间。利用计时器计时此半周期时间,每当计时到后就将输出方波的 I/O(P1.7)反相,然后重复计时此半周期时间再对 I/O 反相,就可在 P1.7脚得到此频率的方波。将 P1.7 经过驱动电路与蜂鸣器相连,随着 P1.7 口输出不同频率的方波,蜂鸣器便会发出不同的声音。音乐的节拍是由延时实现的,如果 1 拍的时间为 0.4 秒,1/4 拍是 0.1 秒。只要设定延时时间,就可得到节拍的时间。延时实现基本延时时间,节拍值只能是它的整数倍。每个音节相应的定时器初值计算公式如下:(1/2)*(1/f)=

3、(12/fose)*(2 16-x)即 x=2 16-(fose/24f)其中,f 是音调频率,当晶振 fosc=11.0592MHz 时,音节“1”相应的定时器初值为 x,则可得到 x=63777D=F921H,其它的可同样得到。表(1) 音节与频率的关系 音调频率(Hz) X(HEX)1 262 F9212 294 F9E13 330 FA8C4 349 FAD85 392 FB686 440 FBE97 494 FC5B2i 523 FC8F在编写歌曲代码过程中,音高由三位数字组成:个位是表示17 这七个音符;十位是表示音符所在的音区:1-低音,-中音,-高音;百位表示这个音符是否要升半

4、音: 0-不升,-升半音。音长最多由三位数字组成:个位表示音符的时值,其对应关系是:|数值(n): |0 |1 |2 |3 | 4 | 5 | 6 |几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2n十位表示音符的演奏效果(0-2): 0-普通,-连音,-顿音,百位是符点位: 0-无符点,1-有符点。2键盘扫描将单片机P1.0P1.7(引脚18)与键盘上对应引脚相连,其中P1.0P1.3控制键盘的行,P1.4P1.7控制键盘的列,这次使用的键盘是4行4列,键盘上的第一行到第四行由8位十六进制代码的低四位控制,即第一行若有键按下,则8位十六进制代码的后四位为0x8,第二行有按

5、键按下,则后四位代码为0x4,依此规律类推;键盘上的第一列到第四列由8位十六进制代码的高四位控制,即第一列若有键按下,则8位十六进制代码的前四位为0x8,第二列有按键按下,则前四位代码为0x4,依此规律类推。综上所述,可以根据8位十六进制的高四位和低四位数据,分别确定按下的键处于第几行第几列,从而确定按键的位置,实现键盘扫描的功能。 3LCD 显示根据写命令函数 wrcomd 和写数据函数 wrdata 分别控制 LCD 的命令写入和数据写入。具体操作方法是由写命令函数 wrcomd 编程控制数据输入的行列,再由写数据函数 wrdata 编程写入需要在 LCD 上显示的数据或应执行的操作,结合

6、两个命令一起控制 LCD 显示。四产品展示3五.实验程序#ifndef _DRIVEFUTION_H_#define _DRIVEFUTION_H_/*EEPROM 函数*/*/* 关闭 ISP,IAP 功能 */ void ISP_IAP_disable(void) ISP_CONTR = 0X00; ISP_CMD = 0X00; ISP_TRIG = 0x00; /*字节读 */ uchar Byte_read(uint byte_addr) EA = 0; /关中断 ISP_CONTR = En_Wait_TIME; /开启 ISP/IAP;并送等待时间 ISP_CMD = Read_

7、COM; /送字节读命令字 ISP_ADDRH = (uchar)(byte_addr 8); /送地址高字节 ISP_ADDRL = (uchar)(byte_addr /送地址低字节 ISP_TRIG = 0X46; /送触发命令字 0X46、0XB9 ISP_TRIG = 0XB9; 4_nop_(); ISP_IAP_disable(); /关闭 ISP/IAP 功能 EA = 1; /开中断 return (ISP_DATA); /*字节编程 */ void Byte_program(uint byte_addr, uchar isp_iap_data) EA = 0; /关中断 I

8、SP_CONTR = En_Wait_TIME; /开启 ISP/IAP;并送等待时间 ISP_CMD = Prog_COM; /送字节编程命令字 ISP_ADDRH = (uchar)(byte_addr 8); /送地址高字节 ISP_ADDRL = (uchar)(byte_addr /送地址低字节 ISP_DATA = isp_iap_data; /送数据进 ISP_DATA ISP_TRIG = 0X46; /送触发命令字 0X46、0XB9 ISP_TRIG = 0XB9; _nop_(); ISP_IAP_disable(); /关闭 ISP/IAP 功能 EA = 1; /开中

9、断 /* 扇区擦除 */ void Sector_erase(uint sector_addr) EA = 0; /关中断 ISP_CONTR = En_Wait_TIME; /开启 ISP/IAP;并送等待时间 ISP_CMD = Dele_COM; /送扇区擦除命令字 ISP_ADDRH = (uchar)(sector_addr 8); /送地址高字节 ISP_ADDRL = (uchar)(sector_addr /送地址低字节 ISP_TRIG = 0X46; /送触发命令字 0X46、0XB9 ISP_TRIG = 0XB9; _nop_(); ISP_IAP_disable();

10、 /关闭 ISP/IAP 功能 EA = 1; /*写入函数 */void EEPROM_write(uint addr, uchar in_data)Sector_erase(addr);Byte_program(addr,in_data); /*EEPROM 函数*/*/5/*音乐播放相关子函数 */*/void InitialSound(void) /初始化定时器BeepIO = 0;Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; / 计算 TL1 应装入的初值 (10ms 的初装值)Sound_Temp_TL1 = (65535-(1

11、/1200)*SYSTEM_OSC)%256; / 计算 TH1 应装入的初值 TH1 = Sound_Temp_TH1;TL1 = Sound_Temp_TL1;TMOD |= 0x11;ET0 = 1;ET1 = 0;TR0 = 0;TR1 = 0;EA = 1;void BeepTimer0(void) interrupt 1 /音符发生中断函数BeepIO = !BeepIO;TH0 = Sound_Temp_TH0;TL0 = Sound_Temp_TL0;/*END*/*/*LCD 操作子函数 */*/void wrcomd(char comd) /写入命令cs = 0; _nop

12、_();rs = 0; _nop_();e = 1; _nop_();rw = 0; _nop_();P0 = comd; _nop_();rw = 0; _nop_(); _nop_();rw = 1; _nop_(); _nop_(); _nop_(); _nop_();void wrdata(char data_wri) /往液晶中写入数据cs = 0; _nop_();rs = 1; _nop_();6e = 1; _nop_();rw = 0; _nop_();P0 = data_wri; _nop_();rw = 0; _nop_(); _nop_();rw = 1; _nop_(

13、); _nop_(); _nop_(); _nop_();void bmp(char data_write,int row_start,int row_end,uchar column_start,uchar column_end) /刷屏子函数 /初始化设置,对屏幕清零 ,默认值,为0,0,8,2,132unsigned char i,j;int num_3;char num_0=0xb0;/uchar column_h,column_l;num_0+=row_start; for(i=row_start;i4); /设置列,先写入高 4 位再写入低四位wrcomd(0x00|(0x0ffo

14、r(j=column_start;j4);wrcomd(0x00|(0x0ffor(j=0;j7|page-(unsigned char)0xb0=0;j-)write_word(number,j,12+5*16,6,8,16);delay(5000);void menu_first_symbol(int choose) /菜单选择符刷新子函数,即“打钩项”bmp(0,0,8,4,18);write_word(menu_one,20,4,choose*2,16,16); /*音乐播放显示函数 */*/void music_display_one(unsigned char s,unsigned

15、 int x) /显示最底层子函数int i;bmp(0,2,8,18+x*16,34+x*16); for(i=3;i0;i-)if(s!=0)write_word(display,1,20+16*x,2*i,16,16);s=s-1;elsewrite_word(display,0,20+16*x,2*i,16,16);/delay(200);void music_display_two(unsigned int p_x) /显示次底层子函数int sign;sign=mc_sizep_x0;if(sign)if(!sizep_x) 10sign=0;mc_sizep_x0=sign;mc

16、_sizep_x1=0;elsemusic_display_one(sizep_x,p_x);mc_sizep_x1+=1;if(mc_sizep_x13)sizep_x-=1;else sizep_x+=1; /*/elsebmp(0,2,8,18+p_x*16,34+p_x*16); write_word(display,2,20+16*p_x,6,16,16);/delay(500);/*/void music_display_three(unsigned int mc) /音符状态置位函数mc_sizemc-10=1;mc_sizemc-11=1;sizemc-1=1;void mus

17、ic_display_four(void) /显示次顶层子函数int i;for(i=0;i= 2; /低音 if (SM=3) CurrentFre 0;i-) /发规定长度的音 while(TF1=0);TH1 = Sound_Temp_TH1;TL1 = Sound_Temp_TL1;TF1=0;display_between_musicplay(SL); /?要结合音长来控制其显示时间,弄清音长问题?if(LDiv3!=0)TR0=0; BeepIO=0;for(i=LDiv3;i0;i-) /音符间的间隔while(TF1=0);TH1 = Sound_Temp_TH1;TL1 =

18、Sound_Temp_TL1;TF1=0;/*/13/*/void music_play_two_1(uchar *Sound,uint *NewFreTab,uint SoundLength,uint LDiv0,uint LDiv1)/播放原存储的音乐uint xdata Point;uchar xdata Tone,Length,i;Point = 0;TR0 = 0;TR1 = 1;for(i=0;i 11)j = j-12;NewFreTabi = FreTabj*2;elseNewFreTabi = FreTabj;if(Octachord = 1)NewFreTabi=2;els

19、e if(Octachord = 3)NewFreTabi2)bmp(0,0,8,0,132);music_state=1;break;case 0x42: Byte_program(start_add+music_counter),0);16write_word(number,0,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break; case 0x88: Byte_program(start_add+music_counter),1);write_word(number,1,4+(m

20、usic_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;case 0x48: Byte_program(start_add+music_counter),2);write_word(number,2,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;case 0x28: Byte_program(start_add+music_counter),3);write_word(number,

21、3,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;case 0x18: Byte_program(start_add+music_counter),4);write_word(number,4,4+(music_counter%48)%16)*8,2+(music_counter%64)/16)*2,8,16);+music_counter;break;case 0x84: Byte_program(start_add+music_counter),5);write_word(n

22、umber,5,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;case 0x44: Byte_program(start_add+music_counter),6);write_word(number,6,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;case 0x24: Byte_program(start_add+music_counter),7);write_

23、word(number,7,4+(music_counter%48)%16)*8,2+(music_counter%48)/16)*2,8,16);+music_counter;break;default:break;void Entry_Music(void) /输入乐谱播放函数uchar gkey,i;bmp(0,0,8,2,132); while(menu_state)for(i=0;i500|realvalue11|realvalue3|realvalue2?0:cho;cho=cho0?2:cho;void menu_second(int choose) /主菜单子函数,用于选中功能

24、子菜单,进入相应的功能子菜单函数 /menu_state=0;switch(choose)case 0:menu_state=0;menu_three1();menu_state=0;break;case 1:music_state=0;Entry_Music();break;case 2:menu_state=0;menu_three2();menu_state=0;break;case 3:menu_state=0;menu_three3();menu_state=0;break;/*/#endif六仿真图及操作流程图23主菜单:1 音乐播放2 数字谱曲3 音乐弹奏4 参数修改1. 让世界

25、充满爱2. 梦醒时分3. 千千阙歌选 1由按键输入音符音长谱曲。由键盘 17控制进行弹奏。1 修改播放速度2 修改歌曲调号3 修改升降八度选22选3选 4七实验中出现的问题及解决方法1在刚开始编写子函数时,编程思想不够明确,子函数设置的比较混乱。经过一段时间的摸索,懂得如何合理分配子函数,比如可以直接调用子函数,将它们互相嵌套,这么做可开始界面:(电子音调发生器)24以极大程度减少程序中的冗余成分,使程序更加简洁明了。2原先我设定蜂鸣器是一端接P3.7,另一端接地,这样的话蜂鸣器是低电平驱动。但是由于单片机输出的驱动电流过小,影响蜂鸣器的播放效果,所以后来将蜂鸣器改成高电平驱动的形式,即使蜂鸣

26、器一端接P3.7,另一端接高电平,使高电平输出的电流从蜂鸣器流过,使蜂鸣器的音量增大。3本次实验的拓展功能之一是LCD显示屏与播放的音符同步显示对应频谱,在编程过程中如何使两者实现同步是一个难点。通过分析之后,采取了尽使播放的音符与显示的频谱之间的延时尽量减少的方法来实现它们的同步。八实验心得与体会本次实验的时间是在小学期,我从七月初开始着手实验准备。首先第一步就是选题,从老师给的题目中我选择了趣味性较大的电子音调发生器,通过阅读单片机课程设计题目中的有关内容,我大致了解了实验的内容、任务与基本原理。然后我开始上网查阅资料,阅读相关程序,利用资源开始了程序编写的工作。应该说这个题目的网上资源较

27、为丰富,所以基本功能编程的大体框架不难确定。除了实现课程设计题目要求的基本功能外,本次实验还实现了一些拓展功能,这些在第二步已进行了详细的阐述,在此我就不再赘述。由于要完成的功能并不少,所以我选择用C语言编程,这样的话比起用汇编来得更方便些。编程占用了我整个实验过程的大部分时间,通过不断的尝试,资料的查阅,同学间互相的帮助,编程工作顺利完成。接下来就是焊板子的工作,由于此实验使用的是单片机,功能比较强大,很多工作可以用程序代替,所以这次板子的构造比较简单,我花了一个下午的时间就将板子焊完了。在调试过程中出现了一些小问题,比如键盘编码问题,仿真电路图也有一些小错误等,在这些问题改正了以后板子就能正常工作了。实验的调试过程还是很迅速的,因为编程阶段,我是一边用开发板烧程序一边用实物直接显示结果的,这样对以后的调试过程的意义很大,能够较大程度的减少调试的工作量,使实验过程更顺利。通过本次的单片机课程设计实验,我重新复习了C语言的使用方法,对于利用单片机在实现功能方面有了更深的体会,尤其是现在可以很熟练的编写歌曲代码了,虽然实验过程中出现了许多的小问题,但每次解决问题的过程对我来说都是一个收获,提醒着我在以后的生活中应认真对待每一件事。总之,通过本次实验学会了很多知识,在以后的学习工作过程中我会学以致用。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报