课程及设计—简易电子琴

2020-01-24 11:59发布

原理图:

(原文件名:2.jpg)
附送程序一份:
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit SPK = P3^6;                   //P3.6外接扬声器
uint FreqTemp;
unsigned char timer0h, timer0l, time;
unsignedchar code num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};
//--------------------------------------
// 晶振采用11.0592MHz
// 频率-半周期数据表 高八位     
code unsigned char FREQH[] = {
    0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8,        //低音1234567
    0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, //1,2,3,4,5,6,7,i
    0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE,           //高音 234567
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF};     //超高音 1234567
// 频率-半周期数据表 低八位
code unsigned char FREQL[] = {
    0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6,        //低音1234567
    0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F,    //1,2,3,4,5,6,7,i
    0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D,             //高音 234567
    0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16};     //超高音 1234567
//按键发声代码
code unsigned char jianyin[] =
{1, 2, 3,  2, 2, 3,  3, 2, 3,  4, 2, 3,  5, 2, 3,  6, 2, 3,  7, 2, 3,  
1, 3, 3,  2, 3, 3,  3, 3, 3,  4, 3, 3,  5, 3, 3,  6, 3, 3,  7, 3, 3};
//世上只有妈妈好数据表      
code unsigned char sszymmh[] = {
6, 2, 3,  5, 2, 1,  3, 2, 2,  5, 2, 2,  1, 3, 2,  6, 2, 1,  5, 2, 1,
6, 2, 4,  3, 2, 2,  5, 2, 1,  6, 2, 1,  5, 2, 2,  3, 2, 2,  1, 2, 1,
6, 1, 1,  5, 2, 1,  3, 2, 1,  2, 2, 4,  2, 2, 3,  3, 2, 1,  5, 2, 2,
5, 2, 1,  6, 2, 1,  3, 2, 2,  2 ,2, 2,  1, 2, 4,  5, 2, 3,  3, 2, 1,
2, 2, 1,  1, 2, 1,  6, 1, 1,  1, 2, 1,  5, 1, 6,  0, 0, 0};
//生日快乐数据表     
code unsigned char srkl[]={
5,1,1,  5,1,1,  6,1,2,  5,1,2,  1,2,2,  7,1,4,
5,1,1,  5,1,1,  6,1,2,  5,1,2,  2,2,2,  1,2,4,
5,1,1,  5,1,1,  5,2,2,  3,2,2,  1,2,2,  7,1,2,  
6,1,2,  4,2,1,  4,2,1,  3,2,2,  1,2,2,  2,2,2,  1,2,4,  0,0,0};
//送别部分数据表     
code unsigned char sb[] = {
5, 2, 2,  3, 2, 1,  5, 2, 1,  1, 3, 4,  6, 2, 2,  1, 3, 1,  6, 2, 1,  5, 2, 4,  0, 0, 0};//中断定义
         void t0int() interrupt 1            //T0中断程序,控制发音的音调
{
    TR0 = 0;                        //先关闭T0
    SPK = !SPK;                     //输出方波, 发音
    TH0 = timer0h;                  //下次的中断时间, 这个时间, 控制音调高低
    TL0 = timer0l;                            
    TR0 = 1;                        //启动T0
}
//延迟函数,即决定半拍数
void delay(unsigned char t)         //延时程序,控制发音的时间长度
{
    unsigned char t1;
    unsigned long t2;
    for(t1 = 0; t1 < t; t1++)       //双重循环, 共延时t个半拍
      for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音
    TR0 = 0;                        //关闭T0, 停止发音
}
//演奏一个音符
void song()                        
{        TR0 = 0;
    TH0 = timer0h;                  //控制音调
    TL0 = timer0l;
    TR0 = 1;                        //启动T0, 由T0输出方波去发音
    delay(time);                     //控制时间长度
}
//生日快乐
void song1()
{          
unsigned char k, i;
              i = 0;
              time = 1;
              while(time)
                          {
              k = srkl + 7 * srkl[i + 1] - 1;          //第i个是音符, 第i+1个是第几个八度
              timer0h = FREQH[k];      //从数据表中读出频率数值
              timer0l = FREQL[k];       //实际上, 是定时的时间长度
              time = srkl[i + 2];          //读出时间长度数值
              i += 3;
              song();                  //发出一个音符
              }          
}
//世上只有妈妈好
void song2()
{unsigned char k, i;       
      
              i = 0;
              time = 1;
              while(time)
                          {
              k = sszymmh + 7 * sszymmh[i + 1] - 1;     //第i个是音符, 第i+1个是第几个八度
              timer0h = FREQH[k];      //从数据表中读出频率数值
              timer0l = FREQL[k];      //实际上, 是定时的时间长度
              time = sszymmh[i + 2];   //读出时间长度数值
              i += 3;
              song();                  //发出一个音符
                }                  //控制时间长度                 
}
//送别
void song3()
{unsigned char k, i;       
              i = 0;
              time = 1;
              while(time)
                          {
              k = sb + 7 * sb[i + 1] - 1;          //第i个是音符, 第i+1个是第几个八度
              timer0h = FREQH[k];      //从数据表中读出频率数值
              timer0l = FREQL[k];      //实际上, 是定时的时间长度
              time = sb[i + 2];   //读出时间长度数值
              i += 3;
              song();                  //发出一个音符
              }                  //控制时间长度
}         
//键盘扫描
//函数返回 : 按下键:返回0~15、如无键按下:返回16
uchar Keyscan(void)
{
    uchar i, j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};
    for(j = 0; j < 4; j++) {    //循环四次,扫描四行
      P1 = Buffer[j];          //在低四位分别输出一个低电平
      _nop_();
      temp = 0x80;            //计划先读出P1.7位
      for(i = 0; i < 4; i++) {     //循环四次,检查四列
        if(!(P1 & temp)) {      //从高四位,截取1位
          return (i + j * 4);     //返回取得的按键值   
        }
        temp >>= 1;            //换右边一位
    } }
    return 16;                 //没有键按下就返回16
}
//控制数码管显示 p2控制数码管的显位
void Display(uchar k)
{
            P2=0xf0;
             P0=num[k];       }
// 主函数
void Main(void)
{
    uchar Key_Value = 16, Key_Temp1, Key_Temp2;//读出的键值
        unsigned char k, i;
    TMOD = 0x01;                  //T0定时方式1
    ET0 = 1;                       //允许T0中断
    EX0 = 1;                       //允许X0中断
    EA = 1;
      while(1) {
          Key_Temp1 = Keyscan();       //读入按键
             if(Key_Temp1 != 16) {         //有键按下
             Display(Key_Value);        //显示键值、延时消抖
             Key_Temp2 = Keyscan();     //再读一次
             if (Key_Temp1 == Key_Temp2) {//两次相等
             Key_Value = Key_Temp1;    //就确认下来
             Display(Key_Value);       //显示
//条件选择语句
switch(Key_Value)
{
    case 12:  
        {
                    song3();
                        delay(10);
                    song1();
                        delay(10);
                        song2();
                        delay(10);  
                    };
    break;  
    case 13:  
    song3();
    break;
    case 14:
    song1();
    break;
    case 15:
    song2();
    break;
    default:
       {   
                     i=  Key_Value*3;
                     k = jianyin + 7 * jianyin[i + 1] - 1;       //第i个是音符, 第i+1个几个八度
             timer0h = FREQH[k];      //从数据表中读出频率数值
             timer0l = FREQL[k];      //实际上, 是定时的时间长度
             time = jianyin[i + 2];   //读出时间长度数值
             song();                  //发出一个音符
            }                  ;
                         break;
} } } } }
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。