带演奏指示灯的电子琴

笔者开发了一种电路,它可以安装在电子琴的按键上。这个电路有64个LED指示灯,64个按键。这64个按键和电子琴共用。电子琴也使用这64个按键弹奏音乐。每个按键对应一个LED灯。电路通过STC89C51单片机控制,当要演奏一首乐曲时,这个乐曲要弹奏的第一个按键上面的LED灯就会亮起来,只有演奏者按下这个按键,这个LED等才会熄灭。同时,当上一个LED灯熄灭以后,这个乐曲要弹奏的第二个按键上面的LED灯就会亮起。只有演奏者按下这个按键,这个LED等才会熄灭。紧接着,这个乐曲要弹奏的第三个按键上面的LED灯就会亮起,同样,只有演奏者按下这个按键,这个LED等才会熄灭。按键上面的LED就按照乐曲要弹奏的按键的顺序亮起,同时,只有演奏者按照乐曲要弹奏的按键的顺序弹奏乐曲,按键上的LED才会熄灭。这样就实现了,演奏者按照乐曲弹奏按键的顺序,也就是按照LED等亮起的顺序,演奏乐曲的功能。也就让一个不会弹琴的人,按照LED的指示来学习弹琴。下面是这个电路的电路图。
电路中,单片机STC89C51控制芯片HD7279A。使用KEILL软件编程。HD7279A控制64个按键和64个LED灯。按照程序,第一个LED亮,当按下第一个按键时,这个LED灭,同时,第二个LED亮,当按下第二个按键时,这个LED灭。这样就实现了按键以此熄灭LED的功能。下面是程序:

#include <reg52.h>

//*** 函数定义 ***

void long_delay(void); // 长延时

void short_delay(void); // 短暂延时

void delay10ms(unsigned char); // 延时10MS

void write7279(unsigned char, unsigned char); // 写入到HD7279

unsigned char read7279(unsigned char); // 从HD7279读出

void send_byte(unsigned char); // 发送一个字节

unsigned char receive_byte(void); // 接收一个字节

//*** 变量及I/O口定义 ***

unsigned char digit[5];

unsigned char key_number, j, k,m,n;

unsigned int tmr;

unsigned long wait_cnter;

unsigned char code dis_code[65]

=

{16,17,1,2};

unsigned char code dis_code1[256]

=

{0,1,2,3,4};

unsigned char code dis_code2[9]

=

{0,1,2,3,4,5,6,7,8};

unsigned char code dis_code3[65]

=

{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

unsigned char code dis_code4[256]

=

{0,1,2,3,4,5,6,7,8,9,10,11,12};

unsigned char code dis_code5[128]

=

{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};

unsigned char code dis_code6[65]

=

{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

unsigned char code dis_code7[256]

=

{0,1,2,3,4,5,6,7,8,9,10};

unsigned char code dis_code8[128]

=

{0,1,2,3,4,5,6,7,8,9,10,11};

unsigned char code dis_code9[128]

=

{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

sbit cs=P1^4; // cs at P1.4

sbit clk=P1^5; // clk 连接于 P1.5

sbit dat=P1^2; // dat 连接于 P1.2

sbit key=P1^3; // key 连接于 P1.3

sbit S1=P0^0; // key 连接于 P1.3

sbit S2=P0^1; // key 连接于 P1.3

//****** HD7279A 指令 ******

#define CMD_RESET 0xa4

#define CMD_TEST 0xbf

#define DECODE0 0x80

#define DECODE1 0xc8

#define CMD_READ 0x15

#define UNDECODE 0x90

#define RTL_CYCLE 0xa3

#define RTR_CYCLE 0xa2

#define RTL_UNCYL 0xa1

#define RTR_UNCYL 0xa0

#define ACTCTL 0x98

#define SEGON 0xe0

#define SEGOFF 0xc0

#define BLINKCTL 0x88

void write7279(unsigned char cmd, unsigned char dta)

{

    send_byte (cmd);

    send_byte (dta);

}

unsigned char read7279(unsigned char command)

{

    send_byte(command);

    return(receive_byte());

}

void send_byte( unsigned char out_byte)

{

    unsigned char i;

    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_byte*2;

    }

    dat=0;

}

unsigned char receive_byte(void)

{

    unsigned char i, in_byte;

    dat=1;                                // set to input mode

    long_delay();

    for (i=0;i<8;i++)

    {

            clk=1;

            short_delay();

            in_byte=in_byte*2;

            if (dat)

            {

                    in_byte=in_byte|0x01;

            }

            clk=0;

            short_delay();

    }

    dat=0;

    return (in_byte);

}

void long_delay(void)

{

    unsigned char i;

    for (i=0;i<0x30;i++);

}

void short_delay(void)

{

    unsigned char i;

    for (i=0;i<8;i++);

}

// ******* 延时n个1MS *******

// ******* 输入:n 延时个数 *******

void delay1ms(unsigned char n)

{

    unsigned int i;

    while(n --)

    {

            for(i = 0;i < 125;i ++);                                  // i ++ ,8μS 左右

    }

}

// ******* 延时n个10MS *******

// ******* 输入:n 延时个数 *******

void delay10ms(unsigned char n)

{

    unsigned int i;

    while(n --)

    {

            for(i = 0;i < 1250;i ++);                                // i ++ ,8μS 左右

    }

}

void delay(void)

{

unsigned int n;

for(n=0;n<10000;n++)

    ;

}

//*** 主程序 ***

//*** 主程序 ***

main()

{

      unsigned char p;

    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)   //使用多分支选择语句

                             {

                               case 1:

                                     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;

                                    case 2:  

                                             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;

                             }

             }          

     }        

}
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值