当前位置:文档之家› 键盘电子乐器

键盘电子乐器

基于AT89S51键盘电子乐器的设计专业班级:设计者:指导老师:设计时间:一、设计目的:键盘电子乐器二、功能要求:利用单片机AT89C51端口作为键盘接口,设计一个具有2个八度音阶的键盘乐器,音阶键不少于16个,采用扫描方式管理键盘,音域范围自行定义。

也可播放1-3首音乐三、方案论证:系统框图设计如图所示:四、系统硬件设计:系统硬件设计如图2所示:图2 系统硬件设计五、软件设计:(1)弹奏程序流程图如图3所示:图3流程图(2)播放歌曲程序流程图如图4图4 流程图(2)程序:/***** 文件名:键盘电子乐器.c*****/#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar Count;void Play_Song(uchar i);sbit ge=P3^0; //歌曲开关按键sbit Speak =P3^7; //扬声器控制脚uint FreqTemp;unsigned int code Freqtab[] = { //定时半周期的初始值64021,64103,64260,64400, //低音3 4 5 664524,64580,64684,64777, //低音7,中音1 2 364820,64898,64968,65030, //中音4 5 6 765058,65110,65157,65178 //高音1 2 3 4};//关于半周期的初始值与频率的关系,可见:/************************************************************* * 函数功能: 用扫描法读P1 外接4×4 键盘* 函数返回: 按下键:返回0~15、如无键按下:返回16**************************************************************/ uchar Keyscan(void){ uchar i, j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};for(j = 0; j < 4; j++) //循环四次,扫描四行{ P1 = Buffer[j]; //在低四位分别输出一个低电平_nop_();temp = 0x80; //计划先读出P1.7位for(i = 0; i < 4; i++) //循环四次,检查四列{ if(!(P1 & temp)) //从高四位,截取1位{return (i + j * 4); //返回取得的按键值}temp >>= 1; //往右边一位}}return 16; //没有键按下就返回16}/************************************************************** * 函数功能:按键数码管显示* 输入: k (键盘数值)***************************************************************/ void Display(uchar k) //数码管显示{ if(k<8)P2 =0xC7 ;elseP2=0x89 ;}void mmkey(void){ uchar Key_Value = 16, Key_Temp1, Key_Temp2;//读出的键值TMOD = 0x01; //T0定时方式1ET1 = 1; //允许T1中断EX1 = 1; //允许外部中断INT1中断允许EA = 1; //开总中断while(1){ if(ge==0)Play_Song(0); //Play_Song(0)为祝你平安Play_Song(1)为路边的野花你不要采TR1 = 0; //暂不发音Key_Temp1 = Keyscan(); //读入按键if(Key_Temp1 != 16) //有键按下{ Display(Key_Value); //显示键值、延时消抖Key_Temp2 = Keyscan(); //再读一次if (Key_Temp1 == Key_Temp2)//两次相等{ Key_Value = Key_Temp1; //就确认下来FreqTemp = Freqtab[Key_Value]; //根据键值,取出定时半周期的初始值Display(Key_Value); //显示TR1 = 1; //启动定时器,发音while (Keyscan() < 16); //等待释放Speak = 0; //停止发音}}}}void T1_INT(void) interrupt 3{ TL1 = FreqTemp; //载入定时半周期的初始值TH1 = FreqTemp >> 8;Speak = ~Speak; //发音}/*以下数组是音符编码*/unsigned char code SONG[] ={ //祝你平安0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,//路边的野华不要采0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20, 0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,0x10,0x1C,0x10, 0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,0x05,0x20,0x10, 0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x30,0x1C,0x10, 0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20, 0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,0x20,0x26,0x40, 0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0x00,};/********************************************************************* 名称: Time0_Init()* 功能: 定时器的初始化,定时时间可用光碟中软件计算,11.0592MZ晶振,10ms * 输入: 无* 输出: 无***********************************************************************/ void Time0_Init(){ TMOD = 0x01;IE = 0x82;TH0 = 0xDC;TL0 = 0x00;}// 名称: Time0_Int()//功能: 定时器中断,中断中实现Count 加一void Time0_Int() interrupt 1{ TH0 = 0xDC;TL0 = 0x00;Count++; //长度加1}/********************************************************************* 名称: Delay_xMs()* 功能: 延时子程序,经过软件调试,测得延时程序大概为55us.* 输入: x* 输出: 无***********************************************************************/ void Delay_xMs(uint x){ uint i,j;for(i=0; i<x; i++){for(j=0;j<3; j++);}}/********************************************************************* 名称: Play_Song()* 功能: 播放扬声器器控制程序* 输入: i (选择播放哪首歌曲,0为“祝你平安”,1为“路边的野花你不要采”* 输出: 无***********************************************************************/ void Play_Song(uchar i){ uchar Temp1,Temp2;uint Addr;Count = 0; //中断计数器清0Addr = i * 217;while(1){ Temp1 = SONG[Addr++];if (Temp1 == 0xFF) //休止符{TR0 = 0;Delay_xMs(100);}else if (Temp1 == 0x00) //歌曲结束符{return;}else{ Temp2 = SONG[Addr++];TR0 = 1; //计时开始while(1){Speak = ~Speak; //P3.7开始发声Delay_xMs(Temp1);if(Temp2 == Count){Count = 0;break;}}}if(ge==1) break; }}void Main(){Time0_Init(); //定时器0中断初始化while(1){ mmkey();}}六、仿真图:如图 5 所示图5 仿真图七、心得体会:这次设计从硬件方面来讲不是很难,程序也相对长一点,但都是书本上所学的知识,主要是中断及其服务程序的编写。

相关主题