当前位置:文档之家› 基于C51单片机音乐盒设计

基于C51单片机音乐盒设计

《汽车单片机技术》课程结课设计报告题目:电子时钟专业班级学号姓名指导教师张琦基于C51单片机音乐盒设计长久以来,音乐都在我们身边,封建时期的编钟道现在我们的各种各样的音乐播放,而音乐盒在我们日常生活中经常拿来当礼物来赠送,音乐盒悠扬的的乐声,经常勾起人们对美好往事的回忆,甚至魂牵梦萦,坠入时光岁月的追忆中。

为了好好利用学到的知识用于自己喜欢的事情中我选择了单片机音乐盒的设计,这让我有回忆起了儿时的美好时光。

1.1 设计内容利用AT89C51的I/O口产生一定频率的方波脉冲,驱动蜂鸣器发出不同的音调,从而演凑乐曲利用PNP三极管进行简单的电路放大。

技术指标:1.利用软件设计编写3首以上的歌曲并通过功放与扬声器播放出来;2.3首歌曲的切换通过3个不同的按键来实现。

3. 能够实现暂停、播放功能。

1.3 系统运行流程1音符频率的产生:音符及定时器初始值:例如:中音1(do)的音频=523hz,周期T=1/523s=1912us定时器/计数器0的定时时间为:T/2=1912/2=956us定时器956us的计数值=定时时间/机器周期(12mhz晶振)=956us/1us=956装入T0计数器初始值为65536-956=64580(0xFC44)将0xFC44装入T0寄存器中(TH0装高八位即TH0=0XFC;TL0装低八位即TL=44),启动T0工作后,每技术956次将产生溢出中断,进入中断服务,每次对P1.0引脚的输出取反,就可得到中音do(523hz)的音符频率。

依此产生其他的不同音符以下给出四个八度的28个频率数据频率-半周期数据表高八位0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音12345670xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 2345670xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567频率-半周期数据表低八位0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音12345670x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 2345670x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16 //超高音 12345672.节拍的产生音乐中的节拍用延时时间产生。

例如:1拍=0.4s,1/2=0.2s,以此类推。

只要求出1/2拍的延时时间,其余节拍是他的倍数就行了。

得到音符并加上起对应的节拍就可得到音调。

以此将音调连起来就可获得曲子。

电路原理1.时钟控制部分:12MHZ晶振1个,30pf瓷片电容2个;2.复位电路:1k电阻1个,22uf电解电容1个;3.发音电路:PNP三极管1个,5v小喇叭1个;4.按键电路:4x4矩阵键盘实现点歌功能;P3.2实现暂停,P3.3实现继续播放;结论:由于时间关系本设计只能单曲播放,不能自动播放下一曲;希在以后能解决,并能实现在连播中进行指定点播和加上数码计时等人性化改进。

通过这次的课程设计不仅让我进一步巩固了所学的单片机只是也让我更进一步了解了单片机的利用,同时我也感受到了学习单片机的乐趣!致谢:感谢这学期来陈海怂老师的悉心教导,让我从一个单片机外汉变成了不再对单片机无从下手的菜鸟。

系统程序#include <reg51.h>unsigned char timer0h, timer0l, time,zt=1;sbit speaker = P1^0;// 频率-半周期数据表高八位共保存了四个八度的28个频率数据code unsigned char FREQH[] = {0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音12345670xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 2345670xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567// 频率-半周期数据表低八位code unsigned char FREQL[] = {0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音12345670x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 2345670x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567//----------------------------------------------------------------------------------------------// 要想演奏不同的乐曲, 只需要修改这个数据表code unsigned char music[4][500] ={//乡间小路数据表{3,1,2, 3,1,1, 3,1,1, 6,0,1, 6,0,1, 1,1,2, 6,0,1, 5,0,1, 6,0,4, 6,0,2, 6,0,1 ,6,0,1, 6,0,2, 6,0,1,1,1,1, 2,1,2, 2,1,1, 3,1,1, 2,1,4, 3,1,1, 3,1,1, 3,1,1, 2,1,1, 4,1,2, 4,1,2, 3,1,2, 2,1,1, 1,1,1,2,1,4, 7,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 5,0,1, 6,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 6,0,4, 6,1,2,3,1,1, 6,1,1, 7,1,1, 6,1,1, 5,1,1, 5,1,2, 5,1,1, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1,3,1,1, 2,1,2, 1,1,1, 2,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,4, 6,1,2, 3,1,1, 6,1,1, 7,1,1, 6,1,1,5,1,1, 5,1,2, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1, 5,1,1, 6,1,1, 4,1,1, 3,1,1, 2,1,2,2,1,2, 5,1,4, 0,0,0},// 送别数据表{ 5,1,2, 3,1,3, 5,1,1, 1,2,3, 6,1,2, 1,2,2, 5,1,4,5,1,2, 1,1,1, 2,1,1, 3,1,2, 2,1,1, 1,1,1, 2,1,4,5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2,1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2, 7,0,1,1,1,4, 6,1,2, 1,2,2, 1,2,4, 7,1,2, 6,1,1, 7,1,1,1,2,4, 6,1,1, 7,1,1, 1,2,1, 6,1,1, 6,1,1, 5,1,1,3,1,1, 1,1,1, 2,1,8, 5,1,2, 3,1,1, 5,1,1, 1,2,2,7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1,4,1,2, 7,0,2, 1,1,4, 0,0,0},//一辈子的孤单数据表{ 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4,5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1,2,1,1, 3,1,1, 3,1,4, 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1, 3,1,1, 2,1,1,1,1,1, 2,1,1, 1,1,1, 1,1,8, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 3,1,1, 2,1,2, 1,1,1, 1,1,1, 5,0,1, 6,0,1,5,0,1, 5,0,6, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1, 3,1,4,5,0,1, 3,1,1, 5,1,2, 6,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1, 3,1,4,5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1, 1,1,1, 1,1,6,3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1, 3,1,6,5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1, 3,1,6,0,0,0},//世上只有妈妈好数据表{6, 2, 3, 5, 2, 1, 3, 2, 2, 5, 2, 2, 1, 3, 2, 6, 2, 1, 5, 2, 1,6, 2, 4, 3, 2, 2, 5, 2, 1, 6, 2, 1, 5, 2, 2, 3, 2, 2, 1, 2, 1,6, 1, 1, 5, 2, 1, 3, 2, 1, 2, 2, 4, 2, 2, 3, 3, 2, 1, 5, 2, 2,5, 2, 1, 6, 2, 1, 3, 2, 2, 2, 2, 2, 1, 2, 4, 5, 2, 3, 3, 2, 1,2, 2, 1, 1, 2, 1, 6, 1, 1, 1, 2, 1, 5, 1, 6, 0, 0, 0}};//-----------------------------------------------------------------------------------------------------------void t0int() interrupt 1 //T0中断程序,控制发音的音调{TR0 = 0; //先关闭T0speaker = !speaker; //输出方波, 发音TH0 = timer0h; //下次的中断时间, 这个时间, 控制音调高低TL0 = timer0l;TR0 = 1; //启动T0}//------------------------------------------------------------------------------------------------------------void delay(unsigned char t) //延时子函数,控制发音的时间长度{unsigned char t1;unsigned long t2;for(t1 = 0; t1 < t; t1++) //嵌套循环, 共延时t个半拍for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音TR0 = 0; //关闭T0, 停止发音}//------------------------------------------------------------------------------------------------------------void song() //演奏一个音符{TH0 = timer0h; //控制音调TL0 = timer0l;TR0 = 1; //启动T0, 由T0输出方波去发音delay(time); //控制时间长度}//-------------------------------------------------------------------------------------------------------------void Song(unsigned char j) //j表示第n+1首曲{ unsigned char k, i;i = 0;time = 1;while(time) {k = music[j][i] + 7 * music[j][i + 1] - 1;//第i个是音符, 第i+1个是第几个八度timer0h = FREQH[k]; //从数据表中读出频率数值timer0l = FREQL[k]; //实际上, 是定时的时间长度time = music[j][i + 2]; //读出时间长度数值i += 3;song(); //发出一个音符}}//---------------------------------------------------------------------------------------------------------------void int_0() interrupt 0 // 紧急情况中断即现实暂停{unsigned char i,k,I,K; //现场保护I=i;K=k;while(zt);zt=1; //回复现场i=I;k=K;}//------------------------------------------------------------------------------------------------------------------void int_1() interrupt 2 // 优先中断即现实继续播放{zt=0;}//-------------------------------------------------------------------------------------------------------------------void main() //程序从这里开始{while(1){unsigned char key_h,key_l,key;P1 =0x00;TMOD = 1; //置T0定时工作方式1ET0 = 1; //开T0中断EA = 1; //开CPU中断EX0=1; //开外部中断0IT0=0;EX1=1; //开外部中断1IT1=1;PX1=1; //开优先中断P2=0xf0; //键盘扫描key_l=P2&0xf0;if(key_l!=0xf0) // 判断是否有按键按下{delay(1) ; //消抖if(key_l!=0xf0) //再次判断是否有按键按下{key_l=P2&0xf0; //扫描列key_l=key_l|0x0f; //得到列值P2=key_l;key_h=P2;key_h=key_h&0x0f; //扫描行key_l=key_l&0xf0; //得到行值key=key_l+key_h; // 得到键值}}switch(key) //判断键值{case 0xee: Song(0); break; //第1首曲注:数组的下标从0开始 case 0xde: Song(1); break;case 0xbe: Song(2); break;case 0x7e: Song(3); break;/* case 0xed: ;break;case 0xdd: ;break;case 0xbd: ;break;case 0x7d: ;break;case 0xeb: ;break;case 0xdb: ;break;case 0xbb: ;break;case 0x7b: ;break;case 0xe7: ;break;case 0xd7: ;break;case 0xb7: ;break;case 0x77: ;break;*/}key=0xf0; //初始化键值}}。

相关主题