Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
制作出来的实物图如下:
单片机源程序如下:
- /************************************************************************
- *硬件连接:二十二个微动开关,一个蜂鸣器,二十一个弹奏键,一个功能切换。 *
- *功 能:电子琴弹奏,按键切换播放。 *
- 弹奏模式切换,添加歌曲。 *
- *添加LED灯模式。 *
- *LED灯状态调试。 *
- ************************************************************************/
- #include<reg51.h>
- sbit QH=P2^7; //P2^7口定义为切换功能
- sbit BUZZ=P1^7; //P1^7口定义为蜂鸣器
- unsigned int H,L; //定时器0缓冲变量
- unsigned char k=0x00; //按键标志位
- void init(void) //初始化程序
- {
- P0=P1=P2=P3=0xff; //初始化P0,P1,P2,P3口将他们的初值全为1
- BUZZ=1; //初始化蜂鸣器鸣器
- QH=1; //初始按键为1关闭状态
- ET0=1; //初始化开定时计数器0中断
- EA=1; //初始化开总中断
- TMOD=0x01; //设计定时计数器timer 0工作方式为1
- }
- void delayms(unsigned int i) //延时1ms程序 用来按键消抖
- {
- unsigned int j;
- while(i--)
- for(j=600;j>0;j--);
- }
- void delay(unsigned int i) //按键延时程序 用来扫描按键 算音长值
- {
- unsigned int j;
- while(i--)
- {
- for(j=600;j>0;j--);
- if(!QH) //判断在唱歌模式是否摁下模式转换按钮
- delayms(10);
- if(!QH)
- {
- k=~k; //如果按下改变标志位的值。
- }
- while(!QH);
- }
- }
- void tanzou(void) //弹奏模式
- {
- unsigned int tone[]={262,294,330,349,392,440,494}; //低音
- unsigned int tone1[]={523,587,659,698,784,880,988}; //中音
- unsigned int tone2[]={1046,1175,1318,1397,1568,1760,1976};//高音
- unsigned int a=0,b=0,c=0; //定义a,b,c三个变量。
- switch(~P1) //高音7键判断键值符合符合键值跳出判断
- { case 0x00:a=0;break;
- case 0x01:a=1;P0=~0x01;break; //按下按钮对应的灯亮
- case 0x02:a=2;P0=~0x02;break; //因为不管是中高低音都有同样的音,所以我们把相同的音放在一个灯上。
- case 0x04:a=3;P0=~0x04;break;
- case 0x08:a=4;P0=~0x08;break;
- case 0x10:a=5;P0=~0x10;break;
- case 0x20:a=6;P0=~0x20;break;
- case 0x40:a=7;P0=~0x40;break;
- }
- if(a!=0) // 判断键值
- {
- H=(65536-1000000/tone[a-1]/2)/256; // 取值,取对应数组中的音值。
- L=(65536-1000000/tone[a-1]/2)%256;
- TH0=H;
- TL0=L; //定时计数器0赋值
- TR0=1; //开定时计数器0
- while(P1!=0xff); //判断按键是否弹起
- TR0=0; //关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- else
- {
- TR0=0; //没有任何按键按下关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- if(a!=1||a!=2||a!=3||a!=4||a!=5||a!=6||a!=7) //如果没有按键按下那么P0口为全1
- {
- P0=0xff;
- }
- switch(~P2) //中音7键
- { case 0x00:b=0;break;
- case 0x01:b=1;P0=~0x01;break;
- case 0x02:b=2;P0=~0x02;break;
- case 0x04:b=3;P0=~0x04;break;
- case 0x08:b=4;P0=~0x08;break;
- case 0x10:b=5;P0=~0x10;break;
- case 0x20:b=6;P0=~0x20;break;
- case 0x40:b=7;P0=~0x40;break;
- }
- if(b!=0) // 中音7键判断键值符合符合键值跳出判断
- {
- H=(65536-1000000/tone1[b-1]/2)/256; // 取值,取对应数组中的音值。
- L=(65536-1000000/tone1[b-1]/2)%256;
- TH0=H;
- TL0=L; //定时计数器0赋值
- TR0=1; //开定时计数器0
- while(P2!=0xff); //判断按键是否弹起 出入不等于全一那么持续响按下的音
- TR0=0; //没有任何键按下关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- else
- {
- TR0=0; //关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- if(a!=1||a!=2||a!=3||a!=4||a!=5||a!=6||a!=7)
- {
- P0=0xff;
- }
- switch(~P3) //低音7键判断键值符合符合键值跳出判断
- {
- case 0x00:c=0;break;
- case 0x01:c=1;P0=~0x01;break;
- case 0x02:c=2;P0=~0x02;break;
- case 0x04:c=3;P0=~0x04;break;
- case 0x08:c=4;P0=~0x08;break;
- case 0x10:c=5;P0=~0x10;break;
- case 0x20:c=6;P0=~0x20;break;
- case 0x40:c=7;P0=~0x40;break;
- }
- if(c!=0)
- {
- H=(65536-1000000/tone2[c-1]/2)/256; // 取值,取对应数组中的音值
- L=(65536-1000000/tone2[c-1]/2)%256;
- TH0=H;
- TL0=L;
- TR0=1;
- while(P3!=0xff); //判断按键是否弹起
- TR0=0; //关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- else
- {
- TR0=0; //没有任何按键按下关定时计数器0
- BUZZ=1; //关蜂鸣器
- }
- if(a!=1||a!=2||a!=3||a!=4||a!=5||a!=6||a!=7)
- {
- P0=0xff;
- }
- }
- void bofang(void) //播放模式
- {
- unsigned int i=0; //定义i=0
- //播放的音调
- unsigned int code tone[]={ 523,587,659,698,784,880,988, //中音7调
- 1046,1175,1318,1397,1568,1760,1976, //高音7调
- 262,294,330,349,392,440,494,99 //低音7调
- };
- //1.茉莉花
- unsigned int code yd[]={3,3,5,6,8,8,6,5,5,6,5,3,3,5,6,8,8,6,5,5,6,5,5,5,5,3,5,6,6,5,
- 3,2,3,5,3,2,1,1,2,1,3,2,1,3,2,3,5,6,8,5,2,3,5,2,3,1,20,19,
- 20,1,2,3,1,2,1,20,19,0,99};
- float code yc[]={ 1,0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,2,1,0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,2,
- 1,1,1,0.5,0.5,1,1,2,1,0.5,0.5,1,0.5,0.5,1,0.5,0.5,2,0.5,0.5,0.5,0.5,1.5,0.5,1,0.5,0.5,2,
- 1,0.5,0.5,0.5,0.5,0.5,0.5,2,1,1,1.5,0.5,0.5,0.5,0.5,0.5,3,1};
- P0=0XFF;
- while(yd[i]!=99)
- {
- H=(65536-1000000/tone[yd[i]-1]/2)/256; // 取值,取对应数组中的音值
- L=(65536-1000000/tone[yd[i]-1]/2)%256;
- TH0=H;
- TL0=L;
- TR0=1;
- delay(400*yc[i]);
- if(k==0x00)break; //如果标志位等于0x00那么跳出播放模式
- TR0=0; //关定时计数器0
- BUZZ=1; //关蜂鸣器
- i++; //i的值每次加1
- if(i==99) break; //当i等于99的时候跳出循环
- }
- }
- void main(void) //主函数
- {
- init(); //调用初始化程序
- while(1)
- {
- if(!QH)
- {
- delayms(10);
- if(!QH)
- { //判断QH是否按下
- k=~k; //两种模式切换
- }
- while(!QH);
- delayms(10);
- }
- switch(k) //判断按键
- {
- case 0x00:tanzou();break; //调用子函数
- case 0xff:bofang();break;
- }
- }
- }
- void timer0(void) interrupt 1 //定时计数器0
- {
- TR0=0; //关定时计数器0
- TH0=H; //接收赋值
- TL0=L; //接收赋值
- BUZZ=~BUZZ; //蜂鸣器发声
- TR0=1; //开定时计数器0
- }
复制代码
原理图Altium Designer PCB文件和代码下载:
电子琴.7z
(11.93 MB, 下载次数: 29)
|