1. 设计要求
设计一个电子琴。利用所给键盘的1,2,3,4,5,6,7,8八个键,能够发出8个不同的音调,并且要求按下按键发声,松开延时一段时间停止,中间再按别的键则发另一音调的声音。
2.Proteus仿真
程序
#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int
sbit Int0 = P3^2;
sbit SPK = P3^3;
unsigned char code freq[][2]={
0xD8,0xF7,//00440HZ 1
0xBD,0xF8,//00494HZ 2
0x87,0xF9,//00554HZ 3
0xE4,0xF9,//00587HZ 4
0x90,0xFA,//00659HZ 5
0x29,0xFB,//00740HZ 6
0xB1,0xFB,//00831HZ 7
0xEF,0xFB,//00880HZ `1
};
uchar High,Low; //定时器预装值的高8位和低8位
uchar num;
uint delay_flag;
void delay(uint i)
{
while(i--);
}
void delay10ms(void)
{
unsigned char a,b,c;
for(c=5;c>0;c--)
for(b=4;b>0;b--)
for(a=248;a>0;a--);
}
void Timer0_Init()
{
TMOD |= 0x11;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=0; //定时器开关关闭
TH1 = 0x0D8; //定时器1,用作延时。
TL1 = 0x0F0;
EA = 1;
ET1 = 1;
TR1 = 0;
}
void Int0Init() //外部中断0
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
void into_Int0()
{
Int0 = 1;
delay10ms();
Int0 = 0;
}
void KeyDown()
{
char a=0;
P1=0xff;
if(P1!=0xff)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(P1!=0xff)//再次检测键盘是否按下
{
//测试列
P1=0xff;
switch(P1)
{
case 0xfe:num= 1;break;
case 0xfd:num= 2;break;
case 0xfb:num= 3;break;
case 0xf7:num= 4;break;
case 0xef:num= 5;break;
case 0xdf:num= 6;break;
case 0xbf:num= 7;break;
case 0x7f:num= 8;break;
}
while((a<50)&&(P1!=0xff)) //检测按键松手检测
{
delay(1000);
a++;
}
into_Int0();
}
}
}
void main()
{
Timer0_Init();
Int0Init();
SPK=0; //在未按键时,蜂鸣器置低
while (1)
{
KeyDown();
}
}
void Int() interrupt 0 //外部中断0的中断函数
{
High=freq[num-1][1];
Low =freq[num-1][0];
TH1 = 0x0D8;
TL1 = 0x0F0;
delay_flag = 0;
TR0 = 1;
TR1 = 1;
}
void Timer0_isr(void) interrupt 1
{
TH0=High;
TL0=Low;
SPK=!SPK;
}
void Timer1Interrupt(void) interrupt 3
{
TH1 = 0x0D8;
TL1 = 0x0F0;
delay_flag++;
if(delay_flag==100)
{
delay_flag = 0;
TR1 = 0;
TR0 = 0;
}
}