笔者开发了一种电路,它可以安装在电子琴的按键上。这个电路有64个LED指示灯,64个按键。这64个按键和电子琴共用。电子琴也使用这64个按键弹奏音乐。每个按键对应一个LED灯。电路通过STC89C51单片机控制,当要演奏一首乐曲时,这个乐曲要弹奏的第一个按键上面的LED灯就会亮起来,只有演奏者按下这个按键,这个LED等才会熄灭。同时,当上一个LED灯熄灭以后,这个乐曲要弹奏的第二个按键上面的LED灯就会亮起。只有演奏者按下这个按键,这个LED等才会熄灭。紧接着,这个乐曲要弹奏的第三个按键上面的LED灯就会亮起,同样,只有演奏者按下这个按键,这个LED等才会熄灭。按键上面的LED就按照乐曲要弹奏的按键的顺序亮起,同时,只有演奏者按照乐曲要弹奏的按键的顺序弹奏乐曲,按键上的LED才会熄灭。这样就实现了,演奏者按照乐曲弹奏按键的顺序,也就是按照LED等亮起的顺序,演奏乐曲的功能。也就让一个不会弹琴的人,按照LED的指示来学习弹琴。下面是这个电路的电路图。
电路中,单片机STC89C51控制芯片HD7279A。HD7279A控制64个按键和64个LED灯。按照程序,第一个LED亮,当按下第一个按键时,这个LED灭,同时,第二个LED亮,当按下第二个按键时,这个LED灭。这样就实现了按键以此熄灭LED的功能。下面是程序:
#include
//函数定义
voidlong_delay(void); //长延时
voidshort_delay(void); //短暂延时
voiddelay10ms(unsignedchar); //延时10MS
voidwrite7279(unsignedchar,unsignedchar); //写入到HD7279
unsignedcharread7279(unsignedchar); //从HD7279读出
voidsend_byte(unsignedchar); //发送一个字节
unsignedcharreceive_byte(void); //接收一个字节
//变量及I/O口定义
unsignedchardigit[5];
unsignedcharkey_number,j,k,m,n;
unsignedinttmr;
unsignedlongwait_cnter;
unsignedcharcodedis_code[65]
=
{16,17,1,2};
unsignedcharcodedis_code1[256]
=
{0,1,2,3,4};
unsignedcharcodedis_code2[9]
=
{0,1,2,3,4,5,6,7,8};
unsignedcharcodedis_code3[65]
=
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsignedcharcodedis_code4[256]
=
{0,1,2,3,4,5,6,7,8,9,10,11,12};
unsignedcharcodedis_code5[128]
=
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
unsignedcharcodedis_code6[65]
=
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
unsignedcharcodedis_code7[256]
=
{0,1,2,3,4,5,6,7,8,9,10};
unsignedcharcodedis_code8[128]
=
{0,1,2,3,4,5,6,7,8,9,10,11};
unsignedcharcodedis_code9[128]
=
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
sbitcs=P1^4; //csatP1.4
sbitclk=P1^5; //clk连接于P1.5
sbitdat=P1^2; //dat连接于P1.2
sbitkey=P1^3; //key连接于P1.3
sbitS1=P0^0; //key连接于P1.3
sbitS2=P0^1; //key连接于P1.3
//HD7279A指令
#defineCMD_RESET0xa4
#defineCMD_TEST0xbf
#defineDECODE00x80
#defineDECODE10xc8
#defineCMD_READ0x15
#defineUNDECODE0x90
#defineRTL_CYCLE0xa3
#defineRTR_CYCLE0xa2
#defineRTL_UNCYL0xa1
#defineRTR_UNCYL0xa0
#defineACTCTL0x98
#defineSEGON0xe0
#defineSEGOFF0xc0
#defineBLINKCTL0x88
voidwrite7279(unsignedcharcmd,unsignedchardta)
{
send_byte(cmd);
send_byte(dta);
}
unsignedcharread7279(unsignedcharcommand)
{
send_byte(command);
return(receive_byte());
}
voidsend_byte( unsignedcharout_byte)
{
unsignedchari;
cs=0;
long_delay();
for(i=0;i<8;i++)
{
if(out_byte&0x80)
{
dat=1;
}
else
{
dat=0;
}
clk=1;
short_delay();
clk=0;
short_delay();
out_byte=out_byte2;
}
dat=0;
}
unsignedcharreceive_byte(void)
{
unsignedchari,in_byte;
dat=1; //settoinputmode
long_delay();
for(i=0;i<8;i++)
{
clk=1;
short_delay();
in_byte=in_byte2;
if(dat)
{
in_byte=in_byte|0x01;
}
clk=0;
short_delay();
}
dat=0;
return(in_byte);
}
voidlong_delay(void)
{
unsignedchari;
for(i=0;i<0x30;i++);
}
voidshort_delay(void)
{
unsignedchari;
for(i=0;i<8;i++);
}
//延时n个1MS
//输入:n延时个数
voiddelay1ms(unsignedcharn)
{
unsignedinti;
while(n--)
{
for(i=0;i<125;i++); //i++,8μS左右
}
}
//延时n个10MS
//输入:n延时个数
voiddelay10ms(unsignedcharn)
{
unsignedinti;
while(n--)
{
for(i=0;i<1250;i++); //i++,8μS左右
}
}
voiddelay(void)
{
unsignedintn;
for(n=0;n<10000;n++)
;
}
//主程序
//主程序
main()
{
unsignedcharp;
p=0;//将i初始化为0
while(1)
{
if(S1==0)//如果S1键按下
{ delay10ms(20);
//延时一段时间
if(S1==0)//如果再次检测到S1键按下
p++;//i自增1
delay10ms(20);
//延时一段时间
if(p==4)//如果i=9,重新将其置为1
p=1;
}
switch(p)//使用多分支选择语句
{
case1:
for(j=0;j<256;)
{
write7279(SEGON,dis_code1[j]); //将64个显示段逐个点亮
if(!key) //如果有键按下
{
key_number=read7279(CMD_READ); //读出键码
if(key_number==dis_code1[j]) //如果有键按下
{
write7279(SEGOFF,dis_code1[j]); //将64个显示段逐个点亮
delay10ms(20);
j++;
}
}
}
break;
case2:
for(j=0;j<256;)
{
write7279(SEGON,dis_code[j]); //将64个显示段逐个点亮
if(!key) //如果有键按下
{
key_number=read7279(CMD_READ); //读出键码
if(key_number==dis_code[j]) //如果有键按下
{
write7279(SEGOFF,dis_code[j]); //将64个显示段逐个点亮
delay10ms(20);
j++;
}
}
break;
default://缺省值,关闭所有LED
P0=0xff;
}
}
}
}
|
|