基于51单片机的简易电子琴系统

该博客围绕51单片机音乐切换系统展开,介绍了系统由STC89C52单片机等构成,具备数码管显示音符、按键切换乐曲等功能。阐述了51单片机特性,采用多种研究方法进行设计,给出原理图、程序及仿真实现,还提供了丰富资料获取途径。

目录

具体实现功能

设计介绍

51单片机简介

设计思路

设计内容

原理图(AD19)

程序(Keil5)

仿真实现(protues8.7)

全部资料


具体实现功能

系统由STC89C52单片机+数码管+电源电路+音符按键+乐曲切换按键+蜂鸣器构成。

具体功能:

1、数码管显示所按的音符

2、从左到右的按键实现的音符分别是:do、re、mi、fa、so、la、si、do(高音);

3、三个按键可实现三首歌的切换:A是《挥着翅膀的女孩》,B是《同一首歌》,C是《两只蝴蝶》。

设计介绍

51单片机简介

51单片是一种低功耗、高性能CMOS-8位微控制器,具有8K可编程Flash存储器,使得其为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。

51系列单片机具有以下标准功能:

8k字节Flash,512字节RAM,

32位I/O口线,看门狗定时器,

内置4KB EEPROM,

MAX810复位电路,

三个16位定时器/计数器,

一个6向量2级中断结构,

全双工串行口。

另外, 51系列在空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机停止工作,直到下一个中断或硬件复位为止。本设计所使用的芯片可兼容以下所有的51系列单片机(包括AT系列和STC系列)。

设计思路

文献研究法:搜集整理相关研究资料,阅读文献,为研究做准备;

调查研究法:通过调查、分析、具体实验等方法,发现相关存在问题和解决办法;

比较分析法:比较不同设计的具体原理,以及同一类传感器性能的区别,分析系统的研究现状与发展前景;

软硬件设计法:通过软硬件设计实现硬件,最后测试各项功能是否满足要求。

设计内容

原理图(AD19)

本系统原理图设计采用Altium Designer19,具体如图。

程序(Keil5)

本设计利用KEIL5软件实现程序设计,主函数如下:

void main() 	//主函数入口
{
	Time0_Init();	//定时器T0初始化
	Speak=1;		//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
	while(1)	//无限循环	
	{
		switch(P1)		//switch语句判断检测 P1按键状态
		{  
			case 0xfe:	//P1=0xfe    "do"按键按下 			
						delay_ms(10);	//延时去抖	
						if(P1==0xfe)	//再判断"do"按键是否按下
						{				
							SMG=table[1];	//数码管显示"1"	
							i=0;			//i置0
		                    TR0=0;  		//关闭定时器T0
							sth=Music_Code[2*i];	//定时器高八位赋值 "do"
						  stl=Music_Code[2*i+1];	//定时器低八位赋值 "do"
							TR0=1;			//启动定时器T0
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测
							{							 				
								delay_ms(10);		//延时一下
								if(P1==0xfe) continue;	//"do"按键按下,跳出(继续发音)
								else break;			//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)	
							{
								while(P1==0xfe);	//等待按键松开									 				
								delay_ms(10);		//延时去抖
								if(P1==0xfe) continue;	
								else break;			//确定松开,退出
							}
							TR0=0;		//关闭定时器T0
						}
						break;			//返回
			case 0xfd:	//P1=0xfd	"re"按键按下 		
						delay_ms(10);	//延时去抖
						if(P1==0xfd)	//再判断"re"按键是否按下
			        	{
							SMG=table[2];	//数码管显示"2"
							i=1;			//i置1
							TR0=0;  		//关闭定时器T0
							sth=Music_Code[2*i];	//定时器高八位赋值 "re"
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "re"
							TR0=1;			//启动定时器T0		
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测
							{									 				
								delay_ms(10);	//延时一下	
								if(P1==0xfd) continue;	//"re"按键按下,跳出(继续发音)	
								else break;		//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
								while(P1==0xfd);	//等待按键松开
								delay_ms(10);		//延时去抖
								if(P1==0xfd) continue;	
								else break;			//确定松开,退出
							}
						}
						TR0=0;			//关闭定时器T0
						break;			//返回
			case 0xef:	//P1=0xef	"mi"按键按下 
						delay_ms(10);	//延时去抖			
						if(P1==0xef)	//再判断"mi"按键是否按下
						{
							SMG=table[3];	//数码管显示"3"
							i=2;			//i置2	
							TR0=0;  		//关闭定时器T0	
							sth=Music_Code[2*i];	//定时器高八位赋值 "mi"	
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "mi"
							TR0=1;			//启动定时器T0	
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测
							{							 				
								delay_ms(10);	//延时一下
								if(P1==0xef) continue;	//"mi"按键按下,跳出(继续发音)
								else break;		//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
								while(P1==0xef);	//等待按键松开	
								delay_ms(10);		//延时去抖
								if(P1==0xef) continue;
								else break;			//确定松开,退出
							}
						}
						TR0=0;			//关闭定时器T0
						break;			//返回		
			default: 	break;			//没有P1没有按键按下,返回
	    }
		switch(P3)		//switch语句判断检测 P3按键状态
		{
			case 0xfe:	//P3=0xfe	"fa"按键按下 
						delay_ms(10);	//延时去抖	
						if(P3==0xfe)	//再判断"fa"按键是否按下
						{
							SMG=table[4];	//数码管显示"4"
							i=3;			//i置3
							TR0=0;  		//关闭定时器T0	
							sth=Music_Code[2*i];	//定时器高八位赋值 "fa"	
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "fa"
							TR0=1;			//启动定时器T0	
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测	
							{							 				
								delay_ms(10);	//延时一下
								if(P3==0xfe) continue;	//"fa"按键按下,跳出(继续发音)
								else break;		//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
								while(P3==0xfe);	//等待按键松开
								delay_ms(10);		//延时去抖
								if(P3==0xfe) continue;
								else break;			//确定松开,退出
							}
						}
						TR0=0;		//关闭定时器T0	
						break;		//返回
			case 0xf7: 	//P3=0xf7	"so"按键按下 
						delay_ms(10);	//延时去抖			
						if(P3==0xf7)	//再判断"so"按键是否按下
						{
							SMG=table[5];	//数码管显示"5"	
							i=4;			//i置4			
							TR0=0;  		//关闭定时器T0		
							sth=Music_Code[2*i];	//定时器高八位赋值 "so"
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "so"
							TR0=1;			//启动定时器T0		
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测	
							{									 				
								delay_ms(10);		//延时一下
								if(P3==0xf7) continue;	//"so"按键按下,跳出(继续发音)
								else break;			//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
							   	while(P3==0xf7);	//等待按键松开		
								delay_ms(10);		//延时去抖
								if(P3==0xf7) continue;
								else break;			//确定松开,退出
							}
					  	}
						TR0=0;		//关闭定时器T0
						break;		//返回
			case 0xef: 	//P3=0xef	"la"按键按下
						delay_ms(10);	//延时去抖
						if(P3==0xef)	//再判断"la"按键是否按下
						{
							SMG=table[6];	//数码管显示"6"
							i=5;			//i置5
							TR0=0;  		//关闭定时器T0
							sth=Music_Code[2*i];	//定时器高八位赋值 "la"
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "la"
							TR0=1;			//启动定时器T0		
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测	
							{							 				
								delay_ms(10);		//延时一下
								if(P3==0xef) continue;	//"la"按键按下,跳出(继续发音)
								else break;			//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
								while(P3==0xef);	//等待按键松开	
								delay_ms(10);		//延时去抖
								if(P3==0xef) continue;
								else break;			//确定松开,退出
							}	
						}
						TR0=0;		//关闭定时器T0	
						break;		//返回
			case 0xdf: 	//P3=0xdf	"si"按键按下
						delay_ms(10);	//延时去抖
						if(P3==0xdf)	//再判断"si"按键是否按下
						{
							SMG=table[7];	//数码管显示"7"	
							i=6;			//i置6
							TR0=0;  		//关闭定时器T0
							sth=Music_Code[2*i];	//定时器高八位赋值 "si"
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "si"
							TR0=1;			//启动定时器T0	
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测	
							{							 				
								delay_ms(10);		//延时一下
								if(P3==0xdf) continue;	//"si"按键按下,跳出(继续发音)
								else break;			//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
								while(P3==0xdf);	//等待按键松开
								delay_ms(10);		//延时去抖
								if(P3==0xdf) continue;
								else break;			//确定松开,退出
							}
						}
						TR0=0;		//关闭定时器T0
						break;		//返回
			case 0xbf:	//P3=0xbf	"高音do"按键按下
						delay_ms(10);	//延时去抖	
						if(P3==0xbf)	//再判断"高音do"按键是否按下
						{
							SMG=table[1]&0x7f;  //数码管显示"1"带小数点(1.)
							i=7;		//i置7		
							TR0=0;  	//关闭定时器T0
							sth=Music_Code[2*i];	//定时器高八位赋值 "高音do"
							stl=Music_Code[2*i+1];	//定时器低八位赋值 "高音do"
							TR0=1;		//启动定时器T0			
							for(j=0;j<=1000;j++)	//软件延时,在一定时间里检测		
							{							 				
								delay_ms(10);		//延时一下
								if(P3==0xbf) continue;	//"高音do"按键按下,跳出(继续发音)
								else break;			//松开了,则返回
							}
							SMG=0xff;	//关闭数码管显示
							Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
							TR0=0;		//关闭定时器T0
							for(;;)
							{
							   	while(P3==0xbf);	//等待按键松开
								delay_ms(10);		//延时去抖
								if(P3==0xbf) continue;
								else break;			//确定松开,退出
							}
						}
						TR0=0;		//关闭定时器T0
						break;		//返回
			default: 	break;		//没有P3没有按键按下,返回
		}
		
		if(Key1==0)			//按键1按下(播放 "挥着翅膀的女孩")
		{
			delay_ms(10);	//延时去抖
			if(Key1==0)		//再判断按键1是否按下
			{
				SMG=table[10];	//数码管显示"A"
				for(i=0;Music_hzcb[i]!=0xff;i++)	//for循环语句			
				{				//Music_hzcb[]=0ff时,跳出for循环语句,停止播放音乐
					sth=yinfu1[(Music_hzcb[i]%100)/10-1][((Music_hzcb[i]%10)-1)*2];	 //定时器高八位赋值
					stl=yinfu1[(Music_hzcb[i]%100)/10-1][((Music_hzcb[i]%10)-1)*2+1];//定时器低八位赋值
					i++;		//i加1
					TR0=1;		//启动定时器T0
					delay_ms(4*500/length[Music_hzcb[i]%10]);	//确定几分音符(节拍)		
					TR0=0;		//节拍结束,关闭定时器T0				 
				}
				SMG=0xff;	//关闭数码管显示
				Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
				for(;;)
				{
					while(Key1==0);		//等待按键松开	
					delay_ms(10);		//延时去抖
					if(Key1==0) continue;
					else break;			//确定松开,退出	
				}
			}
		}
		if(Key2==0)			//按键2按下(播放 "同一首歌")	
		{
			delay_ms(10);	//延时去抖
			if(Key2==0)		//再判断按键2是否按下
			{
				SMG=table[11];	//数码管显示"B"
				for(i=0;Music_tyshg[i]!=0xff;i++)	//for循环语句
				{				//Music_tyshg[]=0ff时,跳出for循环语句,停止播放音乐
					sth=yinfu1[(Music_tyshg[i]%100)/10-1][((Music_tyshg[i]%10)-1)*2];  //定时器高八位赋值
					stl=yinfu1[(Music_tyshg[i]%100)/10-1][((Music_tyshg[i]%10)-1)*2+1];//定时器低八位赋值
					i++;		//i加1
					TR0=1;		//启动定时器T0
					delay_ms(4*500/length[Music_tyshg[i]%10]);	//确定几分音符(节拍)
					TR0=0;		//节拍结束,关闭定时器T0						 
				}
				SMG=0xff;	//关闭数码管显示
				Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
				for(;;)	
				{
					while(Key2==0);		//等待按键松开	
					delay_ms(10);		//延时去抖
					if(Key2==0) continue;
					else break;			//确定松开,退出
				}
			}
		}
		if(Key3==0)			//按键3按下(播放 "两只蝴蝶")
		{		
			delay_ms(10);	//延时去抖	
			if(Key3==0)		//再判断按键3是否按下
			{
				SMG=table[12];	//数码管显示"C"		
				for(i=0;Music_lzhhd[i]!=0xff;i++)	//for循环语句
				{				//Music_lzhhd[]=0ff时,跳出for循环语句,停止播放音乐
					sth=yinfu1[(Music_lzhhd[i]%100)/10-1][((Music_lzhhd[i]%10)-1)*2];  //定时器高八位赋值
					stl=yinfu1[(Music_lzhhd[i]%100)/10-1][((Music_lzhhd[i]%10)-1)*2+1];//定时器低八位赋值
					i++;		//i加1	
					TR0=1;		//启动定时器T0
					delay_ms(4*500/length[Music_lzhhd[i]%10]);	//确定几分音符(节拍)
					TR0=0;		//节拍结束,关闭定时器T0					 
				}
				SMG=0xff;	//关闭数码管显示
				Speak=1;	//蜂鸣器端口置1 (让蜂鸣器处于与电源5V断电状态)
				for(;;)
				{
					while(Key3==0);		//等待按键松开
					delay_ms(10);		//延时去抖
					if(Key3==0) continue;
					else break;			//确定松开,退出
				}
			}
		}
	}
}

代码运行截图:

仿真实现(protues8.7)

本设计利用protues8.7软件实现仿真设计。

全部资料

全部资料包括程序(KEIL5)、AD原理图(AD19)、protues仿真(protues8.7)、参考论文(仅供参考)、开题报告、任务书、实物图、讲解视频、软硬件设计框图等,具体如图,全网最全!!

资料获取:
https://docs.qq.com/doc/DSXZnZHl4cVhkTk5p

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值