单片机编程 音乐编程程序

发布者:skyhcg最新更新时间:2016-09-27 来源: eefocus关键字:单片机编程  音乐编程 手机看文章 扫描二维码
随时随地手机看文章
#include 

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long


sbit BEEP=P2^0; //喇叭输出脚

uchar th0_f; //在中断中装载的T0的值高8位
uchar tl0_f; //在中断中装载的T0的值低8位
uchar key;

/*------------------------------------------------
                   函数声明
------------------------------------------------*/
uchar keyscan(void);//键盘扫描程序
void delay(uint i); //延时子程序

/*-------- T0的值,及输出频率对照表 --------------*/
uchar code freq[36*2]={
    0xA9,0xEF,            //0x3F,0XEE,//00220HZ ,1 //0
 0x93,0xF0,            //0X3D,0XEF,//00233HZ ,1#
 0x73,0xF1,            //0X30,0XF0,//00247HZ ,2
 0x49,0xF2,            //0X18,0XF1,//00262HZ ,2#
 0x07,0xF3,            //0XE6,0XF1,//00277HZ ,3
 0xC8,0xF3,             //0XB7,0XF2,//00294HZ ,4
 0x73,0xF4,             //0X71,0XF3,//00311HZ ,4#
 0x1E,0xF5,             //0X2A,0XF4,//00330HZ ,5
 0xB6,0xF5,             //0XCF,0XF4,//00349HZ ,5#
 0x4C,0xF6,             //0X72,0XF5,//00370HZ ,6
 0xD7,0xF6,             //0X09,0XF6,//00392HZ ,6#
 0x5A,0xF7,             //0X97,0XF6,//00415HZ ,7
 0xD8,0xF7,              //0X20,0XF7,//00440HZ 1   //12
 0x4D,0xF8,              //0X9F,0XF7,//00466HZ 1#  //13
 0xBD,0xF8,              //0X18,0XF8,//00494HZ 2   //14
 0x24,0xF9,              //0X88,0XF8,//00523HZ 2#  //15
 0x87,0xF9,              //0XF3,0XF8,//00554HZ 3   //16
 0xE4,0xF9,              //0X59,0XF9,//00587HZ 4   //17
 0x3D,0xFA,               //0X05,0XFA,//00622HZ 4# //18
 0x90,0xFA,              //0X13,0XFA,//00659HZ 5   //19
 0xDE,0xFA,               //0X66,0XFA,//00698HZ 5# //20
 0x29,0xFB,             //0XB9,0XFA,//00740HZ 6    //21
 0x6F,0xFB,               //0X05,0XFB,//00784HZ 6# //22
 0xB1,0xFB,                //0X4D,0XFB,//00831HZ 7 //23
 0xEF,0xFB,                 //0X90,0XFB,//00880HZ `1
 0x2A,0xFC,                 //0XD0,0XFB,//00932HZ `1#
 0x62,0xFC,                //0X0C,0XFC,//00988HZ `2
 0x95,0xFC,                   //0X44,0XFC,//01046HZ `2#
 0xC7,0xFC,               //0X7B,0XFC,//01109HZ `3
 0xF6,0xFC,                 //0XAD,0XFC,//01175HZ `4
    0x22,0xFD,                  //0XDD,0XFC,//01244HZ `4#
    0x4B,0xFD,                 //0X0A,0XFD,//01318HZ `5
    0x73,0xFD,                //0X35,0XFD,//01397HZ `5#
    0x98,0xFD,              //0X5D,0XFD,//01480HZ `6
    0xBB,0xFD,               //0X83,0XFD,//01568HZ `6#
    0xDC,0xFD,                 //0XA6,0XFD,//01661HZ `7 //35
};

//定时中断0,用于产生唱歌频率
timer0() interrupt 1
{
   TL0=tl0_f;TH0=th0_f; //调入预定时值
   BEEP=~BEEP; //取反音乐输出IO
}

//音乐符号串解释函数
//入口:要解释的音乐符号串,输出的音调串,输出的时长串
changedata(uchar *song,uchar *diao,uchar *jie)
{
 uchar i,i1,j;
 char gaodi; //高低+/-12音阶
 uchar banyin;//有没有半个升音阶
 uchar yinchang;//音长
 uchar code jie7[8]={0,12,14,16,17,19,21,23}; //C调的7个值
 *diao=*song;
 for(i=0,i1=0;;)
 {
  gaodi=0; //高低=0
  banyin=0;//半音=0
  yinchang=4;//音长1拍
  if((*(song+i)=='|') || (*(song+i)==' ')) i++;
  //拍子间隔和一个空格过滤
  switch(*(song+i))
  {
   case ',': gaodi=-12;i++;//低音
   break;
   case '`': gaodi=12;i++; //高音
   break;
  }
  if(*(song+i)==0) //遇到0结束
  {
   *(diao+i1)=0; //加入结束标志0
   *(jie+i1)=0;
   return;
  }
  j=*(song+i)-0x30; i++; //取出基准音
  j=jie7[j]+gaodi; //加上高低音
  yinc: switch(*(song+i))
  {
   case '#': //有半音j加一个音阶
   i++;j++;
   goto yinc;
   case '-': //有一个音节加长
   yinchang+=4;
   i++;
   goto yinc;
   case '_': //有一个音节缩短
   yinchang/=2;
   i++;
   goto yinc;
   case '.': //有一个加半拍
   yinchang=yinchang+yinchang/2;
   i++;
   goto yinc;
  }
  *(diao+i1)=j; //记录音符
  *(jie+i1)=yinchang; //记录音长
  i1++;
 }
}

//奏乐函数
//入口:要演奏的音乐符号串
void play(uchar *songdata)
{
 uchar i,c,j=0;
 uint n;
 uchar diaodata[48]; //音调缓冲
 uchar jiedata[48]; //音长缓冲
 changedata(songdata,diaodata,jiedata); //解释音乐符号串
 TR0=1;
 for(i=0;diaodata[i]!=0;i++) //逐个符号演奏
 {
  tl0_f=freq[diaodata[i]*2]; //取出对应的定时值送给T0
  th0_f=freq[diaodata[i]*2+1];
  for(c=0;c   { key = keyscan();
   for(n=0;n<29500;n++); // 29500
   if(key != 0xff)//((!K1)||(!K2)||(!K3)||(!K4))//发现按键,立即退出播放
   {
    TR0=0;
    return;
   }
  }
  TR0=0;
  for(n=0;n<460;n++); //460音符间延时
  TR0=1;
 }
 TR0=0;
}

//一分钱
uchar code yifenqian[]={
                  "5`1|6_`1_5|3_5_2_3_|5-|"
                  "3_5_6_`1_|5_6_5_3_|1.3__|2-|"
                  "3_2_1_2_|3-|6_5_3_5_|6-|"
                        "5_`1_6_5_|3_5_2|5_2_3_2_|1-|"
                        };

//世上只有妈妈好
uchar code mamahao[]={
                      "6.5_35|`16_5_6-|35_6_53_2_|1_,6_5_3_2-|"
                      "2.3_55_6_|321-|5.3_2_1_,6_1_|,5--"
                     };
//找朋友
uchar code zhaopengyou[]={ "5_6_5_6_|5_6_5|5_`1_7_6_|5 3|"
                         "5_5_3_4_|5_5_3|1_4_3_2_|1_2_1|"
                       };
//茉莉花
uchar code molihua[]={"33_5_6_`1_`1_6_|55_6_5-|33_5_6_`1_`1_6_|55_6_5-|"
                       "5553_5_|665-|32_3_53_2_|11_2_1|"
                       //"3_2_1_3_2.3_|56_`1_5-|23_5_2_3_1_,6_|,5-,61|"
                       //"2.3_1_2-1_,6_|,5--"
       };
//新年好
uchar code xinnianhao[]={
   "1_1_1 ,5|3_3_3 1|1_3_5 5|4_3_2-|"
   "2_3_4-|3_2_3 1|1_3_2 ,5|,7_2_1-|"
};
//小星星
uchar code xingxing[]={
                       "1155|665-|4433|221-|"
                       "5544|332-|5544|332-|"
                       "1155|665-|4433|221-|"
};
//外婆的澎湖湾
uchar code waipodephw[]={
                        "3_5_5_5_6_`1_6_5_|`1_`1_`1_6_5-|"
                        "`3_`3_`3_`3_`4_`3_`2_`1_|`2_`2_`2_`3_`2-|"
                        "`3_`3_`3_`3_`4_`3_`2_`1_|6_`1_`1_6_5-|"
                        };
}

//春天在哪里
uchar code chuntian[]={"3_3_3_1_|,5,5|3_3_3_1_|3-|5_5_3_1_|,5_,5_,5|,6_,7_1_3_|2-|"
                       "3_3_3_1_|,5,5|3_3_3_1_|3-|5_6_5_6_|5_4_3_1_|,53|1-|"
                      };

//两只老虎
uchar code laohu[]={"1231|1231|345-|345-|5_6_5_4_31|5_6_5_4_31|"
                    "151-|151-"
                   };

/*------------------------------------------------
              键盘扫描程序
------------------------------------------------*/
uchar keyscan(void)  //键盘扫描函数,使用行列反转扫描法
{
  uchar cord_h,cord_l;//行列值中间变量
  P3=0x0f;            //行线输出全为0
  cord_h=P3&0x0f;     //读入列线值
  if(cord_h!=0x0f)    //先检测有无按键按下
  {
    delay(100);        //去抖
    if(cord_h!=0x0f)
    {
       cord_h=P3&0x0f;  //读入列线值
       P3=cord_h|0xf0;  //输出当前列线值
       cord_l=P3&0xf0;  //读入行线值
       return(cord_h+cord_l);//键盘最后组合码值
    }
   }
   return(0xff);     //返回该值
}
/*------------------------------------------------
                 延时程序
------------------------------------------------*/
void delay(uint i)  //延时函数
{
 while(i--);
}
//乐谱方式输入的音乐播放,
void main(void) // 主程序
{
 uchar code jie8[8]={12,14,16,17,19,21,23,24};//1234567`1八个音符在频率表中的位置
 uchar i = 0;
    uchar n = 0;
 TMOD = 0x01; //使用定时器0的16位工作模式
 TR0 = 0;
 ET0 = 1;
 EA = 1;
 
 while(1)
 { 
   key = keyscan();
   switch(key)
   {
     case 0x7e:
         while(key == 0x7e)
       {
        key = keyscan();
       }
       play(molihua);
       break;//0
     case 0x7d:
         while(key == 0x7d)
       {
        key = keyscan();
       }
       play(yifenqian);
       break;//1
     case 0x7b: while(key == 0x7b)
         {
        key = keyscan();
       }
       play(chuntian);
       break;//2
     case 0x77: while(key == 0x77)
         {
        key = keyscan();
       }
       play(waipodephw);
       break;//3
     case 0xbe: while(key == 0xbe)
         {
        key = keyscan();
       }
       play(xingxing);
       break;//4
     case 0xbd: while(key == 0xbd)
         {
        key = keyscan();
       }
       play(xinnianhao);
       break;//5
     case 0xbb: while(key == 0xbb)
         {
        key = keyscan();
       }
       play(mamahao);
       break;//6
     case 0xb7: while(key == 0xb7)
         {
        key = keyscan();
       }
       play(zhaopengyou);
       break;//7
     case 0xde: while(!(key ^ 0xde))
       {
        tl0_f=freq[jie8[0]*2]; //置一个音符的值
        th0_f=freq[jie8[0]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }
         break;//8
     case 0xdd: while(!(key ^ 0xdd))
       {
        tl0_f=freq[jie8[1]*2]; //置一个音符的值
        th0_f=freq[jie8[1]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       } 
       break;//9
     case 0xdb: while(!(key ^ 0xdb))
       {
        tl0_f=freq[jie8[2]*2]; //置一个音符的值
        th0_f=freq[jie8[2]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }
       break;//a
     case 0xd7: while(!(key ^ 0xd7))
       {
        tl0_f=freq[jie8[3]*2]; //置一个音符的值
        th0_f=freq[jie8[3]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }
       break;//b
     case 0xee: while(!(key ^ 0xee))
       {
        tl0_f=freq[jie8[4]*2]; //置一个音符的值
        th0_f=freq[jie8[4]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }break;//c
     case 0xed: while(!(key ^ 0xed))
       {
        tl0_f=freq[jie8[5]*2]; //置一个音符的值
        th0_f=freq[jie8[5]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }break;//d
     case 0xeb: while(!(key ^ 0xeb))
       {
        tl0_f=freq[jie8[6]*2]; //置一个音符的值
        th0_f=freq[jie8[6]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }break;//e
     case 0xe7: while(!(key ^ 0xe7))
       {
        tl0_f=freq[jie8[7]*2]; //置一个音符的值
        th0_f=freq[jie8[7]*2+1];
        TR0 = 1;
        key = keyscan();
        //for(n=0;n<10000;n++); //延时
       }break;//f
    default:   break;
   }
   TR0 = 0;
  /*if(!K1)
  {
      tl0_f=freq[jie8[0]*2]; //置一个音符的值
      th0_f=freq[jie8[0]*2+1];
      TR0 = 1;
      for(n=0;n<10000;n++); //延时
  }
  if(!K2)
  {
      tl0_f=freq[jie8[1]*2]; //置一个音符的值
      th0_f=freq[jie8[1]*2+1];
      TR0 = 1;
      for(n=0;n<10000;n++); //延时
  }
  if(!K3)
  {
      tl0_f=freq[jie8[2]*2]; //置一个音符的值
      th0_f=freq[jie8[2]*2+1];
      TR0 = 1;
      for(n=0;n<10000;n++); //延时
  }
  if(!K4)
  {
      tl0_f=freq[jie8[3]*2]; //置一个音符的值
      th0_f=freq[jie8[3]*2+1];
      TR0 = 1;
      for(n=0;n<10000;n++); //延时
  }
      TR0 = 0;
  if(!K1)
  {
   while(!K1);
   play(molihua); //播放音乐
  }
  if(!K2)
  {
   while(!K2);
   play(dami); //播放音乐
  }
  if(!K3)
  {
   while(!K3);
   play(mamahao); //播放音乐
  }
  if (!K4)
  {
   switch(i)
   {
    case 0:
    play(xianjian); //播放音乐
    break;
    case 1:
    play(song3); //播放音乐
    break;
    case 2:
    play(mamahao); //播放音乐
    break;
    case 3:
    play(boluo); //播放音乐
    break;
    case 4:
    play(xingxing); //播放音乐
    break;
    case 5:
    play(dami); //播放音乐
    break;
   }
   i++;if(i==6)i=0;
  }*/
 }

关键字:单片机编程  音乐编程 引用地址:单片机编程 音乐编程程序

上一篇:单片机 音乐编写 《渴望》
下一篇:C编写8051单片机音乐播放程序

推荐阅读最新更新时间:2024-03-16 15:12

单片机编程如何快速入门?
单片机是一门实践性很强的课程(是半软半硬的东西),所以必须是理论联系实践。 一、什么是单片机呢? 单片机 1、和我们的计算机(电脑)差不多,大家都知道,我们的计算机(电脑)里面有 (1)CPU (2)硬盘 (3)内存 (4)主板 (5)等等。 这些东西是装在一个叫主机的里面的。好大!一个CPU大概要400块,硬盘也要500左右,内存200左右,主板500左右,这些东西加在一起大概要1600块左右。如果配上其他的,一台电脑要3000到4000左右吧。 视图2、但是把这些东西(CPU,硬盘,内存,主板等等)用集成块做好后,如下图所视: 就成了我们要学习的“单片机”
[单片机]
浅谈一下MSP430单片机编程及其优点
MSP430是自己接触的第一种单片机,个人觉得MSP430单片机无论在软件上还是硬件上都很不错。它的编程环境IAR Embedded Workbench,这个编程环境软件很不错,在软件布局上很人性化,用起来很顺手,在调试方面也很方便,支持软件仿真等。 个人觉得,430编程在头文件上做得很好,而且各种型号的芯片的头文件兼容性也不错,在调用头文件里面参数的书写规范上做得很好。所以430在编程上手还不错。430在硬件上功能很强大,个人觉得在以后430的发展空间会更大。低功耗,小巧,功能强大,性价比高。
[单片机]
51单片机编程指令系统中符号的意义
指令的长度 所谓指令的长度,就是描述一条指令所需要的字节数,用一个字节能描指令,同理,用两个字令,同理,用两个字节描述的叫2字节指令,用三个字节描述的指令就叫3字节指令。在这里我们对80C51的111条指令进行了分类: 1字节指令共有49条 2字节指令共有45条 3字节指令共有17条 到底哪条指令是1字节、2字节或者3字节指令,在我们后面的指令表中都可以查阅到的。 这里有一个问题请大家引起注意,在前面的课程中,我们学习过指令计数器PC,PC是一个16位的计数器,那么这个指令计数器是怎样来计数的呢?我们的指令有1字节、2字节、3字节指令。是不是每执行一个字节,这个指令计数器PC就自动加1?答案是错误的!!实际上,PC始终是跟踪着指令的
[单片机]
基于AT89S52单片机的电子万年历系统设计
目前基于单片机控制技术的微电子技术得到空前的发展。广泛应用于各种控制领域、智能领域、仿真领域。控制领域里的定时计时控制、温度控制,在生产、生活等领域已经得到了广泛的应用。液晶显示模块在各种测量仪器、测量装置、显示仪表等日用电子产品中的应用越来越广泛,并且对器件的测量精度和显示精度的要求也越来越高,尤其是对时间的测量不但要求准确,而且需要读取数值更直观更方便。本文以AT89S52单片机为主控芯片,以DALLAS公司推出的实时时钟芯片DS1302为时钟控制芯片,以1602液晶显示模块为显示器,进行电子万年历系统的设计。本系统可同屏显示年、月、日、星期、温度以及闹钟设置等功能。 1 系统总体设计 本系统以STC89S52单片机为核
[单片机]
基于AT89S52单片机的电子万年历系统设计
自学单片机编程之流水灯
对于编程来说,我是一个大菜鸟。也许对于会的人我的记录都是小儿科,但我是记录给自己看的,是记录自己的学习脚步的。一边学习,一边记录,一边温故而知新。 对于机器人制作我是一窍不通,它也很复杂,没个一年半载的都搞不出来,主要分为几个大块如编程、步进电机控制、电路板制作、机械制作等。现在我学习编程这 块,机械制作在平时一点一点积累,就没有总结记录什么了。程序我是在14年3月初接触的,之前学习的是模电的知识 , 为后面其他的知识打个基础吧!当然也可以一直学模电,不过对于我来说还是算了吧,不能说太难反正不容易,也许我对它不是太感冒!现在是针对学习,我报了机 械组,也如愿的进入了机械组。努力快点自己制作出自己的机器人!(学长的机器人就不错还获得
[单片机]
自学<font color='red'>单片机编程</font>之流水灯
十个51单片机编程小技巧
1.定义的变量不要太多。低128位为用户定义变量的存放区域(默认时),也可以把变量放在高128位,但容易出错,尽量少放,最好不放。通过M51可以查看内存变量的存放,最好不要超过110个字节,否则程序无法运行或出错。 2.如一个变量多处使用可定义为全局变量。例如循环变量i、j,尽量减少参数传递。 3.静态变量最好放在程序存储区,用code定义。 4.变量应定义为无符号数,像标志位等仅占一位的变量应定义为bit。 5.子程序在main()主程序之后的应事先声明,放在前面的不用声明。 6.变量、子程序定义但没使用,系统给出警告。 7.虽然局部变量和全局变量不同名,但运行时可能被全局变量改变。 8.程序在编
[单片机]
51单片机编程实例讲解
通过前面的学习,我们已经掌握了相当一部份的单片机指令,大家对这些枯燥的单片机指令可能也有些厌烦了,下面让我们轻松一下,做个实验。 实验(注意本程序可以在C51单片机实验台上或在Keil C51仿真软件上运行,仿真软件可以在本站下载): ORG 0000H LJMP START ORG 30H START: MOV SP,#5FH MOV A,#80H LOOP: MOV P1,A RL A LCALL DELAY LJMP LOOP delay: mov r7,#255 d1: mov r6,#255 d2: nop nop nop nop djnz r6,d2 djnz r7,d1 r
[单片机]
通过单片机编程在蓝牙技术中的应用方案
下面的文字只是关于蓝芽技术的调制算法方面,我认为只需要将蓝芽模块加在单片机上就可以了,而不必通过单片机编程来实现具体的算法,只需要编写使两个模块的接口就可以,也就是单片机发送信号时的激励程序,接受外来信号后的处理程序。置于其余就由作为硬件设备的蓝芽来自行处理。不过我并不确定,我会查查看的. 蓝牙技术是用于替代电缆或连线的短距离无线通信技术。它需要把数字信号转换成模拟信号以便在空间中传输,它采用的调制方式是高斯频移键控,以下简称GFSK, 要了解GFSK,就要先说说频移键控的原理,以下简称 FSK FSK: 简单的讲,就是用不同的频率来调制不同的码元,比如说二进制,有0和1 两种码元,那么我就需要两个频率f1和f2来调制数字0和
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved