51单片机电子琴

基于51单片机的电子琴制作(播放+弹奏)

制作的电子琴具有播放一段音乐和自我弹奏两种工作模式,可通过按键来切换模式。

程序如下:

#include <reg52.h>   
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P2
typedef unsigned int u16;
typedef unsigned char u8; 
sbit      beep=P1^4; 
sbit LCD1602_E=P1^2;
sbit LCD1602_RW=P1^1;
sbit LCD1602_RS=P1^0;
sbit swtich=P1^3;//切换按键	
uchar timer0h,timer0l,time,flag,key,a,b,c;
u8 moshi[11]="bofangmoshi";
u8 moshi1[11]="tanzoumoshi";
u8 yindiao[7]="1234567";
code uchar song[]={0,1,1,
				   5,1,1,
				   5,1,1,
				   5,1,1,
				   6,1,1,
				   7,1,1,
				   6,1,1,
				   5,1,1,
			       3,1,1,
				   3,1,1,
				   3,1,1,
				   2,1,1,
				   2,1,1,
				   2,1,2,
				   0,1,2,
				   5,1,1,
				   5,1,1,
				   5,1,1,
				   3,1,1,
				   2,1,1,
				   2,1,1,
				   1,1,1,
				   1,1,1,
				   2,1,1,
				   1,1,1};		   
code uchar TH_0[]={0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 
                    0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
                    0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
                    0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;
             
code uchar TL_0[]={0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
                    0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
                    0xEE,0x44, 0x6B,0xB4,0xF4,0x2D, 
                    0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,};
void delay(uchar t)		  
{
	uchar t1;
	unsigned long t2;
	for(t1=0;t1<t;t1++)
	{
		for(t2=0;t2<8000;t2++);
	}
}

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}

void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}

void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;   //写入时序
	Lcd1602_Delay1ms(5);   //保持时间
	LCD1602_E = 0;
}

void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}

void LCD_Display(void)
{
	u8 i;

	LcdWriteCom(0x00+0x80);
	if(flag==1)
	{
		LcdWriteCom(0x01);  
		for(i=0;i<11;i++)
		{
			LcdWriteData(moshi[i]);	
		}

	}
	else
	{
		for(i=0;i<11;i++)
		{
			LcdWriteData(moshi1[i]);	
		}
		LcdWriteCom(0x40+0x80);
		for(i=0;i<1;i++)
		{
			LcdWriteData(yindiao[c]);
		}
	} 

}

void check_key()  //按键函数
{
	P3=0xff;//先赋给P2组口高电平
	switch(P3)//按下一个键
	{
		case 0xfe:key=7;c=0;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xfd:key=8;c=1;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xfb:key=9;c=2;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xf7:key=10;c=3;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xef:key=11;c=4;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xdf:key=12;c=5;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		case 0xbf:key=13;c=6;TH0=TH_0[key];
	TL0=TL_0[key];
	TR0=1;break;
		default:beep=1;TR0=0;			   //没有按键按下关闭喇叭
	}
}
void songd()				 //  音乐处理函数
{
	TH0=timer0h;
	TL0=timer0l;
	TR0=1;
	delay(time);                       
}




void main(void)//主函数
{
	uchar k,i;
	LcdInit();	
	TMOD=1; 			//置CT0定时工作方式1
	EA=1;
	ET0=1;
	flag=0;				//IE=0x82 //CPU开中断,CT0开中断 
	while(1)												                          
	{
		if(swtich==0)
		{
			flag=1;
			i=0;
			LCD_Display();  
			while(i<75)				  //音乐数组长度 ,放完循环播放  
			{              
				k=song[i]+7*song[i+1]-1;
				timer0h=TH_0[k];
				timer0l=TL_0[k];
				time=song[i+2];
				i=i+3;
				songd();
				if(swtich==1)
					break;
			}
		}
		else
		{
			flag=0;
			check_key();
			LCD_Display();		
		}
	} 
}
void t0int() interrupt 1		//定时器中断函数
{
	if(flag==1)
	{
		TR0=0;
		beep=~beep;
		TH0=timer0h;
		TL0=timer0l;
		TR0=1;
	}
	else
	{
		beep=~beep;
		TH0=TH_0[key];
		TL0=TL_0[key];

	}
}

数组song[]中存放我们想要播放的歌曲每三个数代表音乐简谱中的一个音的音调,节拍,时间(本人对音乐不是很了解,求指正),可以通过改变数组的长度和内容来存放不同的音乐。
可通过开关切换至弹奏模式,通过按不同的按键来发出不同的音调(长按某个按键会一直发出其对应的音调,轻触按键即可)

proteus仿真

示例图片如下(播放元件选用喇叭播放出来的声音效果要比选用蜂鸣器的效果要好的多)。

proteus仿真图
亲测可用,如有错误望各位大佬不吝指正。

  • 24
    点赞
  • 326
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值