简易电子琴设计(c语言)

目录

1  设计内容:

1.1 矩阵键盘代表琴键,实现至少8个音的弹奏,分别为1,2,3,4,5,6,7,i.

1.2 键按下时间的长短代表节拍的长短

1.3 用蜂鸣器发出声音

1.4 8*8led点阵动态显示音符高低(自用显示)

2  系统硬件设计

2.1 硬件组成

2.2 显示模块

 2.3 按键模块

 2.4 发音模块

3  系统主程序流程图

4  protues原理图

5  AD的pcb图

6  程序代码

 


1  设计内容:

1.1 矩阵键盘代表琴键,实现至少8个音的弹奏,分别为1,2,3,4,5,6,7,i.

1.2 键按下时间的长短代表节拍的长短

1.3 用蜂鸣器发出声音

1.4 8*8led点阵动态显示音符高低(自用显示)

2  系统硬件设计

2.1 硬件组成

本次设计简易电子琴,通过STC89C52芯片最小控制电路,以16位矩阵电盘,蜂鸣器产生16个音阶,8x8点阵led显示音符高低,独立按键控制复位。将不同模块结合起来,实现简易电子琴的设计。

硬件以ST89C52芯片为核心,外部扩展4x4矩阵式键盘来模拟16个按键,用蜂鸣器来发声,外部扩展8*8LED点阵来动态显示音符的简谱。

基本引荐结构图如图2所示。

                                                        图2

2.2 显示模块

点阵屏的8个行引脚与单片机的P0口相连并且接上拉电阻;而点阵的8个列引脚则直接与单片机的P2口相连。

       显示模块的电路图如图2.1所示。

 2.3 按键模块

16位矩阵键盘,通过P1口控制音阶的产生和led点阵显示,按下相应的的键产生设定的声音和点亮对应的led点阵屏,按键模块的电路图如图2.3所示。

                                                 图2.3

 2.4 发音模块

使用无源蜂鸣器,通过内部程序产生不同频率的方波,使蜂鸣器产生16个基本的音阶,16个按键分别是中音和高音的Do,Re,Mi,Fa,So,La,Si,Do.蜂鸣器与P3^6相接,电路图如图2.4所示。

                                                                        图2.4

3  系统主程序流程图

4  protues原理图

 

5  AD的pcb图

 

6  程序代码

#include <reg51.h> 
#include<intrins.h>
#include<absacc.h>
//#define PA XBYTE[0xff7c]
//#define PB XBYTE[0xff7d]
//#define PC XBYTE[0xff7e]
#define CTRL XBYTE[0xff7f]
#define temp P1
#define uchar unsigned char

uchar code Table_of_Digits[] = {                       //8*8led点阵段码 ,1~f 

0xFF,0xFF,0xF9,0xFB,0xFB,0xFB,0xF1,0xFF,/*"1",0*/

0xFF,0xFF,0xF8,0xFA,0xFD,0xFE,0xF8,0xFF,/*"2",1*/

0xFF,0xFF,0xF8,0xFB,0xFD,0xFB,0xF8,0xFF,/*"3",2*/

0xFF,0xFF,0xFB,0xF9,0xFA,0xF0,0xF1,0xFF,/*"4",3*/

0xFF,0xFF,0xF8,0xF8,0xFB,0xFB,0xF8,0xFF,/*"5",4*/

0xFF,0xFF,0xF9,0xF8,0xFA,0xFA,0xF8,0xFF,/*"6",5*/

0xFF,0xFF,0xF9,0xFB,0xFB,0xFB,0xFB,0xFF,/*"7",6*/

0xFF,0xFF,0xF8,0xFA,0xFD,0xFA,0xF8,0xFF,/*"8",7*/

0xFF,0xFF,0xF8,0xFA,0xF8,0xFB,0xFC,0xFF,/*"9",8*/
0xFF,0xFF,0xFF,0xF8,0xFB,0xF8,0xF0,0xFF,/*"a",0*/

0xFF,0xFD,0xFD,0xF9,0xF9,0xF9,0xF9,0xFF,/*"b",1*/

0xFF,0xFF,0xFF,0xF9,0xFE,0xFE,0xF8,0xFF,/*"c",2*/

0xFF,0xF9,0xFB,0xF8,0xFA,0xFA,0xF8,0xFF,/*"d",3*/

0xFF,0xFF,0xFF,0xF9,0xF9,0xF9,0xF9,0xFF,/*"e",4*/

0xFF,0xF9,0xFD,0xF8,0xFD,0xFD,0xF8,0xFF,/*"f",5*/
};

void delay(unsigned int z); //延时函数,参数为非负整型,延时1ms 
void display( int yin) ;      //led显示函数,参数为整型,
void function1 (void) ;       //该函数用于主函数中的按键发音 和点阵显示 
int keyscan();                //键盘扫描并返回键值 
unsigned int pin[]={64580,64684,64777,64820,64898,64985,65030,65058,65110,65157,65178,65217,65252,65265,65283,65290};//16个音阶简谱码(T值) 
unsigned int syin[16]={	0};                 //存储16音阶 
sbit P36=P3^6;                             //beep蜂鸣器引脚 
int yin,i;
unsigned poe;                              //用于存储按键扫描函数返回的键值            
unsigned char key_num;                     

main()                                                                                 //??? 
{  EA=1;                          //总中断允许 
	TMOD=0x01;                   //定时器T0工作方式1 
	ET0=1;                       //T0中断允许 
	PT0=1;                      //T0为高级中断 
	CTRL=0x89;
	while(1)
	{
		function1();
	}
	}

void function1 (void)            //按键返回值存储,长按发音和显示 
{ poe = keyscan();               //???????? 
   switch(poe)
   
  {
  case  1:yin=1;	            //按键对应的音阶 
                  break;
  case  2:yin=2;	 
				  break;
  case  3:yin=3;	 
				  break;
  case  4:yin=4;	 
				  break;
  case  5:yin=5;	  
				  break;
  case  6:yin=6;	 
				 ;break;
  case  7:yin=7;		
				  break;
  case  8:yin=8;	  
				  break; 
	 case  9:yin=9;	 
          break;
  case  10:yin=10;	 
				  break;
  case  11:yin=11;	 
				  break;
  case  12:yin=12;	 
				  break;
  case  13:yin=13;	  
				  break;
  case  14:yin=14;	 
				 ;break;
  case  15:yin=15;		
				  break;
  case  16:yin=16;	  
				  break;}
if(poe!=0xff)				           //按键按下 
  { if (yin==1)	{ 
  			  	   TH0=pin[yin-1]/256;    //寻找对应的简谱码给T0赋值,以获取相应的脉冲,蜂鸣器按照相应的频率发音 
				TL0=pin[yin-1]%256;
				  while(poe==1)
				  {
				  	TR0=1;                  //定时器开始计数 
					poe = keyscan();       //用于不断扫描,判断键值是否还等于while小括号里面的值,如果等于,说明按键没有松开,则进入中断实现发音。 
				  display(yin -1 );
					}
				  TR0=0;
				  
                  }
  if (yin==2){ 
  			  			TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==2)
				  {
				  	TR0=1;
					poe = keyscan();
						
					display(yin -1 );	
				  }
				  TR0=0;
				  
				  }
  if (yin==3) {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==3)
				  {
				  	TR0=1;
			poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				  

				  }
  if (yin==4)	 {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==4)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				  
				  }
  if (yin==5)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==5)
				  
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				  
				  }
 if (yin==6)	 {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==6)
				  {
				  	TR0=1;
					poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				  
				  }
  if (yin==7)	{
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==7)
				  {
				  	TR0=1;
			poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				  
				  }
 if (yin==8)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==8)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
  if (yin==9)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==9)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==10)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==10)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==11)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==11)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==12)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==12)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==13)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==13)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==14)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==14)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==15)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==15)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
				  }
				  TR0=0;
				 
		   	}
	 if (yin==16)  {
						TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
				  while(poe==16)
				  {
				  	TR0=1;
				poe = keyscan();
						
						display(yin -1 );
//					display(syin);
				  }
				  TR0=0;
				 
		   	}
 for (i=15;i>0;i--)
			  	  syin[i]=syin[i-1];
			syin[0]=yin;
				  }	P36=1;

				  
			
		}
 

					
		void delay(unsigned int z)		              //延时函数,延时1ms 
{
	unsigned int x,y;
	for(x=z;x>0;x--)
		for(y=125;y>0;y--);
}

 void fasheng() interrupt 1                          //T0 中断 
{
	TH0=pin[yin-1]/256;
	TL0=pin[yin-1]%256;
	P36=~P36;                                       //P3^6引脚发出相应的脉冲信号驱动蜂鸣器发声 
	
}  

int keyscan()                                        //矩阵键盘扫描函数,返回按键值num
    {
       uchar num;
       temp=0xf0;
       if(temp!=0xf0)    //先将高四位全部置高电平,低四位全部置低电平,当高四位不全为高电平时,说明有按键按下,然后通过接受的数据值,判断是哪一列有按键按下
       {
          delay(10);    //延时10ms消抖 
          if(temp!=0xf0)   
          {
             temp=0xf0;     
             switch(temp)   
             {
                case 0x70: num=1;  break;  
                case 0xb0: num=5;  break;   
                case 0xd0: num=9;  break;   
                case 0xe0: num=13; break;   
             }
             temp=0x0f;     
             switch(temp)   
             {
                case 0x07: num=num+0; break; 
                case 0x0b: num=num+1; break;   
                case 0x0d: num=num+2; break;  
                case 0x0e: num=num+3; break;   
             }
          }
					else
						num = 0xff;
       }
       return num;  
    }
		
		void display(yin)
		{
			uchar i;
				for(i = 0 ;i < 8;i++)
				{
					P0= i%8;                                              //位值 
					P2 = Table_of_Digits[i+yin*8];                    //段码 
					delay(1);
					P2 = 0xff;                                               //熄灭 
				}
		}

 

  • 19
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@简单就好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值