电子琴

https://blog.csdn.net/weixin_34724366/article/details/80642207

#include <reg51.h>
#define u16 unsigned int
#define u8 unsigned char

#define GPIO_KEY P1
#define GPIO_DIG P0
sbit beep = P3^0;

/*******************************全局变量******* *******************/    //initNum = 65536   - 1/(2 * f[keyValue]) ;
//三个八度的频率
u8 code f[24]  = {
    261,294,330,349,392,440,493,370,
    523,587,659,698,784,880,988,740,
    1047,1175,1319,1397,1568,1760,1976,1480
};
u8 code ledSegment  [16] = {0x3f,   0x06,   0x5b,   0x4f,   0x66,   0x6d,
                        0x7d,   0x07,   0x7f,   0x6f,   0x77,
                        0x7c,   0x39,   0x5e,   0x79,   0x71};

u8 KeyValue;
u16 initNum;
u8 high;
u8 low;
float temp ;
/***************************************************************/

/*
判断哪个按键按下,对应一个频率
计时器按该频率对应的周期的一半计时,每次计时结束时,蜂鸣器反转

65535个计数,一个计数1微秒
我要计时多久呢?
1/2f = 0.5/f 秒
是多少微秒呢?
(500000)/(f) 

所以最长能计65.535 毫秒
260 : 1.9ms
1480:  0.337ms
*/
void delay(u16 i)
{
    while(i--);
}
void keyDown()
{
    //char a = 0;
    GPIO_KEY = 0x0f;  //高四位低电平,第四位高电平
    if(GPIO_KEY!= 0x0f)
    {
        delay(1000);
        if(GPIO_KEY!= 0x0f)
        {
            //--------------------------求按键列数----------------------------------//
            switch(GPIO_KEY)
            {
                case(0x07):  KeyValue = 0; break;       //0000 0111  : 第一列
                case(0x0b):  KeyValue = 1; break;       //0000 1011  : 第二列
                case(0x0d):  KeyValue = 2; break;       //0000 1101  : 第三列
                case(0x0e):  KeyValue = 3; break;       //0000 1110  : 第四列
            }
            //--------------------------求按键行数----------------------------------//
            GPIO_KEY = 0xf0;  //高四位高电平,第四位低电平   
            switch(GPIO_KEY)
            {
                case(0x70):  KeyValue += 0; break;    //第一行 
                case(0xb0):  KeyValue += 4; break;      
                case(0xd0):  KeyValue += 8; break;       
                case(0xe0):  KeyValue += 12; break;     //第四行
            }
            //--------------------------求计数初值----------------------------------//           
            temp = 500000/f[KeyValue];
            initNum =(int) (65536   - temp) ;
            low = initNum &  0x00ff;
            high = initNum >>8 ;
            //--------------------------开始计时----------------------------------//
                //赋初值
                TH0 =  high;
                TL0 = low;
                //开始
                TR0=1;
            //退出条件:按键松开
            while(GPIO_KEY!= 0xf0)         //   GPIO_KEY!= 0xf0 说明按键还没松,此时CPU始终在此循环中
            {

            }
        }
    }   
}

void T0Init()
{   
    TMOD |= 0x01;            //1.选择工作方式,给TMOD 赋值    ,这里选T0,方式一  
    ET0 = 1 ;           //3. 中断允许:总允许和T0允许
    EA = 1;
}

void main(void)
{
    T0Init();   
    while(1)
    {
        keyDown();
        GPIO_DIG = ~ledSegment[KeyValue];
    }
}
//计时器0的调用程序
void Timer0() interrupt 1             //    T0溢出时引用
{   
    //退出条件:按键松开 
    if(GPIO_KEY!= 0xf0)         //   GPIO_KEY!= 0xf0 说明按键还没松,此时放音乐
    {
        //TH0 =  high;
        //TL0 = low;
        TH0 =  0xf7;
        TL0 = 0x22;
        beep = ~beep;
        /*beep=~beep;
        delay(200);    */
    }   
        
}

猜你喜欢

转载自www.cnblogs.com/YuQiao0303/p/9910425.html
今日推荐