stanle1 发表于 2011-7-28 10:07:54

课程及设计—简易电子琴

原理图:
http://cache.amobbs.com/bbs_upload782111/files_43/ourdev_661556P5XUGT.jpg
(原文件名: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 - 1;          //第i个是音符, 第i+1个是第几个八度
            timer0h = FREQH;      //从数据表中读出频率数值
            timer0l = FREQL;       //实际上, 是定时的时间长度
            time = srkl;          //读出时间长度数值
            i += 3;
            song();                  //发出一个音符
            }          
}
//世上只有妈妈好
void song2()
{unsigned char k, i;       
      
            i = 0;
            time = 1;
            while(time)
                          {
            k = sszymmh + 7 * sszymmh - 1;   //第i个是音符, 第i+1个是第几个八度
            timer0h = FREQH;      //从数据表中读出频率数值
            timer0l = FREQL;      //实际上, 是定时的时间长度
            time = sszymmh;   //读出时间长度数值
            i += 3;
            song();                  //发出一个音符
                }                  //控制时间长度                 
}
//送别
void song3()
{unsigned char k, i;       
            i = 0;
            time = 1;
            while(time)
                          {
            k = sb + 7 * sb - 1;          //第i个是音符, 第i+1个是第几个八度
            timer0h = FREQH;      //从数据表中读出频率数值
            timer0l = FREQL;      //实际上, 是定时的时间长度
            time = sb;   //读出时间长度数值
            i += 3;
            song();                  //发出一个音符
            }                  //控制时间长度
}       
//键盘扫描
//函数返回 : 按下键:返回0~15、如无键按下:返回16
uchar Keyscan(void)
{
    uchar i, j, temp, Buffer = {0xfe, 0xfd, 0xfb, 0xf7};
    for(j = 0; j < 4; j++) {    //循环四次,扫描四行
      P1 = Buffer;          //在低四位分别输出一个低电平
      _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;       }
// 主函数
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 - 1;       //第i个是音符, 第i+1个几个八度
             timer0h = FREQH;      //从数据表中读出频率数值
             timer0l = FREQL;      //实际上, 是定时的时间长度
             time = jianyin;   //读出时间长度数值
             song();                  //发出一个音符
            }                  ;
                       break;
} } } } }

stanle1 发表于 2011-7-28 14:48:39

虽然 程序技术含量不高··但是用无源的~~可以实现啊~为啥没人看的~~~

df890170 发表于 2011-8-16 20:18:32

回复【1楼】stanle1
-----------------------------------------------------------------------

这是一部份的程序代码吗
我没办法组译ㄝ

chenming1989 发表于 2011-8-16 22:33:57

我用fpga做过,还不错

mzbhy 发表于 2011-8-16 23:19:02

掌声鼓励。

wxzakcldw 发表于 2011-8-17 07:14:16

楼主电路图到是画的挺好的嘛,这种东西我没做过,不过应该不是很难,赞一个先!

machongchang 发表于 2011-9-3 08:25:57

我也正在研究这个呢

带疤的公爵 发表于 2012-5-3 22:32:49

原理图来个清晰点的就好了{:sleepy:}

lxa0 发表于 2012-5-3 23:58:05

对楼主的这个很感兴趣
可惜看不懂C语言

stanle1 发表于 2012-6-21 22:14:14

这个东东其实是不错的 一个课程设计来的!!!实际做好了!!

刘华淼 发表于 2014-4-7 22:37:06

挺 好 的 !
页: [1]
查看完整版本: 课程及设计—简易电子琴