找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2938|回复: 0
打印 上一主题 下一主题
收起左侧

proteus 51单片机电子琴仿真图加程序

[复制链接]
跳转到指定楼层
楼主

  1. #include <reg52.h>

  2. #define SONG 4                                                                // 歌曲的数量
  3. #define LED_PORT        P3
  4. #define uchar unsigned char                // 以后unsigned char就可以用uchar代替
  5. #define uint  unsigned int                // 以后unsigned int 就可以用uint 代替
  6. #define ulong unsigned long                // 以后unsigned long就可以用ulong代替

  7. sbit Key1_P  = P1^0;                                // 弹奏键1的管脚
  8. sbit Key2_P  = P1^1;                                // 弹奏键2的管脚
  9. sbit Key3_P  = P1^2;                                // 弹奏键3的管脚
  10. sbit Key4_P  = P1^3;                                // 弹奏键4的管脚
  11. sbit Key5_P  = P1^4;                                // 弹奏键5的管脚
  12. sbit Key6_P  = P1^5;                                // 弹奏键6的管脚
  13. sbit Key7_P  = P1^6;                                // 弹奏键7的管脚
  14. //sbit Key8_P  = P1^7;                                // 弹奏键8的管脚
  15. sbit Key9_P  = P2^0;                                // 播放内置歌曲的按键管脚
  16. sbit Key10_P = P2^1;                                // 开始/停止录制
  17. sbit Key11_P = P2^2;                                // 播放录制的歌曲
  18. sbit Beep_P  = P2^4;                                // 扬声器管脚           
  19. sbit Led_P   = P2^7;                                // 录歌指示灯        
  20. sbit Key_Set1  = P2^3;            //设置音区按键1
  21. sbit Key_Set2  = P2^5;            //设置音区按键2
  22. sbit Key_Set3  = P2^6;            //设置音区按键3

  23. uchar gTone=0;                                                        // gTone代表当前要播放的音调
  24. uchar gPlayStatus;                                        // gPlayStatus代表当前的播放状态,0是停止,1是播放
  25. uchar gSong;                                                    // gSong代表当前播放到第几首歌
  26. uchar ledflag=0;            //流水灯的标志位
  27. uchar yinquflag=1;          //音区选择  1:第一组  2:第二组  3:第三组  默认第一组

  28. /*  定时器初值          低1  低2  低3  低4  低5  低6  低7  中1  中2  中3  中4  中5  中6  中7  高1  高2  高3  高4  高5  高6  高7 */
  29. uchar code  ArrTL0[]={ 0X8B,0X5B,0X14,0X66,0X03,0X8F,0X0B,0X43,0XAB,0X08,0X33,0X81,0XC7,0X05,0X21,0X55,0X84,0X99,0XC0,0XE3,0X02};
  30. uchar code  ArrTH0[]={ 0XF8,0XF9,0XFA,0XFA,0XFB,0XFB,0XFC,0XFC,0XFC,0XFD,0XFD,0XFD,0XFD,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFF};
  31. //                      0    1    2    3     4   5    6     7           8   9          10   11   12   13   14   15   16   17   18   19   20
  32.         
  33. /*  数码管的显示值       1    2    3    4    5     6   7 */
  34. uchar code  ArrDig[]={ 0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};


  35. /*  《水手》的乐谱  */
  36. uchar code Music1[]={
  37.         5,4,  9,2,  8,2,  9,4, 8,2,  9,2,      
  38.         10,3, 11,1, 10,2, 8,2, 9,8,  9,1,     
  39.         10,2, 10,1, 9,1,  8,2, 7,1,  7,1,  8,2,  7,1, 7,1, 8,2, 9,2,
  40.         7,2,  6,2,  5,2,  7,2, 6,8,      
  41.         5,4,  9,2,  8,2,  9,4, 8,2,  9,2,        
  42.         10,2, 10,1, 11,1, 9,2, 8,2,  9,8,
  43.         10,3, 9,1,  8,2,  7,2, 8,2,  8,1,  7,1,  8,2, 8,1, 9,1,  
  44.         6,2,  6,2,  5,2,  4,2, 5,8,  
  45.         8,3,  8,1,  8,2,  8,2, 10,2, 10,1, 9,1,  8,2, 7,1, 7,1,
  46.         9,3,  8,1,  7,2,  8,1, 7,1,  5,8,      
  47.         8,3,  8,1,  8,2,  8,2, 8,2,  8,1,  8,1,  8,2, 7,1, 8,1,         
  48.         9,2,  9,2,  9,1,  8,1, 7,1,  8,1,  9,8,
  49.         8,3,  8,1,  8,2,  8,2, 10,2, 9,2,  8,2,  8,2,      
  50.         9,2,  8,2,  7,2,  8,1, 7,1,  5,7,  5,1,         
  51.         8,3,  8,1,  8,2,  8,1, 8,1,  8,2,  8,2,  7,2, 8,2,
  52.         9,2,  9,2,  8,2,  7,2, 9,4,  9,2,  11,2,
  53.         12,4, 11,4, 9,4,  8,2, 7,2,
  54.         8,2,  9,1,  8,1,  7,2, 6,2,  5,4,  5,2,  6,2,
  55.         7,4,  7,2,  9,2,  8,4, 6,1,  5,1,  4,2,
  56.         5,3,  5,1,  7,2,  8,2, 9,4,  9,2,  11,2,
  57.         12,4, 11,4, 9,4,  8,2, 7,2,
  58.         8,2,  9,1,  8,1,  7,2, 6,2,  5,4,  5,2,  6,2,
  59.         7,4,  7,2,  9,2,  8,4, 7,2,  6,2,  5,12
  60.         };

  61. /*  《挥着翅膀的女孩》的乐谱  */
  62. uchar code Music2[]={
  63.         9,4,  9,2,  10,2, 11,4, 7,2,  8,2,      
  64.         9,2,  9,2,  9,2,  10,2, 11,4, 8,2,  9,2,   
  65.         10,4, 10,2, 9,2,  7,4,  10,2, 9,2,
  66.         10,4, 5,2,  7,2,  8,4,  7,2,  8,2,      
  67.         9,4,  9,2,  10,2, 11,4, 12,2, 13,2,        
  68.         14,2, 14,2, 9,2,  10,2, 11,4, 8,2,  9,2,
  69.         10,2, 9,2,  10,2, 14,2, 14,4, 8,2,  9,2,  
  70.         10,2, 9,2,  10,2, 15,2, 15,4, 14,2, 13,2,  
  71.         14,6, 15,2, 16,2, 15,2, 14,2, 13,2,
  72.         14,6, 14,2, 13,2, 11,2, 11,2, 7,2,      
  73.         12,6, 12,2, 11,2, 7,2,  7,2,  9,2,         
  74.         8,6,  9,1,  10,1, 10,2, 11,2, 14,2, 13,2,
  75.         14,6, 15,2, 16,2, 15,2, 14,2, 13,2,      
  76.         14,6, 14,2, 13,2, 11,2, 11,2, 7,2,         
  77.         12,6, 12,2, 11,2, 11,2, 14,2, 13,2,
  78.         14,16
  79.         };

  80. /*  《茉莉花》的乐谱  */                                                         
  81. uchar code Music3[]={
  82.         9,4,  9,2,  11,2, 12,2, 14,2, 14,2, 12,2,  
  83.         11,4, 11,2, 12,2, 11,8,                 
  84.         9,4,  9,2,  11,2, 12,2, 14,2, 14,2, 12,2,
  85.         11,4, 11,2, 12,2, 11,8,                    
  86.         11,4, 11,4, 11,4, 9,2,  11,2,           
  87.         12,4, 12,4, 11,8,
  88.         9,4,  8,2,  9,2,  11,4, 9,2,  8,2,         
  89.         7,4,  7,2,  8,2,  7,8,                  
  90.         9,2,  8,2,  7,2,  9,2,  8,6,  9,2,
  91.         11,4, 12,2, 14,2, 11,8,                    
  92.         8,4,  9,2,  11,2, 8,2,  9,2,  7,2,  5,2,  
  93.         4,8,  5,4,  7,4,  
  94.         8,6,  9,2,  7,2,  8,2,  7,2,  5,2,         
  95.         4,12
  96.         };

  97. /*  《欢乐颂》的乐谱  */
  98. uchar code Music4[]={  
  99.         9,2,  9,2,  10,2, 11,2,   
  100.         11,2, 10,2, 9,2,  8,2,         
  101.         7,2,  7,2,  8,2,  9,2,        
  102.         9,3,  8,1,  8,4,
  103.         9,2,  9,2,  10,2, 11,2,   
  104.         11,2, 10,2, 9,2,  8,2,         
  105.         7,2,  7,2,  8,2,  9,2,        
  106.         8,3,  7,1,  7,4,
  107.         8,2,  8,2,  9,2,  7,2,   
  108.         8,2,  9,1,  10,1, 9,2,  7,2,   
  109.         8,2,  9,1,  10,1, 9,2,         8,2,   
  110.         7,2,  8,2,  4,2,  9,2,
  111.         9,2,  9,2,  10,2, 11,2,   
  112.         11,2, 10,2, 9,2,  10,1, 8,1,   
  113.         7,2,  7,2,  8,2,  9,2,        
  114.         8,3,  7,1,  7,4
  115.         } ;




  116. /*********************************************************/
  117. // 毫秒级的延时函数,time是要延时的毫秒数
  118. /*********************************************************/
  119. void DelayMs(uint time)
  120. {
  121.         uint i,j;
  122.         for(i=0;i<time;i++)
  123.                 for(j=0;j<112;j++);
  124. }



  125. /*********************************************************/
  126. // 发出指定音调及其节拍的声音,tone代表音调,beat代表节拍
  127. /*********************************************************/                 
  128. void PlayTone(uchar tone,float beat)
  129. {
  130.         int i;
  131.         P0=ArrDig[tone%7];                        // 数码管显示当前音调值
  132.         gTone=tone;                                                        // 将音调值赋给全局变量gTone
  133.         TH0 = ArrTH0[tone];                        // 装入定时器TH0的初值
  134.         TL0 = ArrTL0[tone];                        // 装入定时器TL0的初值
  135.         TR0=1;                                                                        // 启动定时器
  136.         for(i=0;i<beat;i++)               
  137.         {
  138.                 DelayMs(200);         
  139.         }
  140.         TR0=0;                                                                        // 停止定时器
  141.         P0=0xff;                                   // 关闭数码管显示        
  142.         Beep_P=1;        
  143. }



  144. /*********************************************************/
  145. // 播放内置的音乐
  146. // arr[]是要播放的乐谱数组,num是数组里面的元素个数
  147. /*********************************************************/
  148. void PlayMusic(uchar music[],uint num)
  149. {
  150.         uint i=0;
  151.         while(i<num)                        
  152.         {   
  153.                 if(gPlayStatus==1)                                                          // 判断播放状态是否为播放还是暂停
  154.                 {   
  155.                         PlayTone(music[i],music[i+1]);        // 开始演奏一个节拍
  156.                         i+=2;                                                                                                                // 进入下一个节拍,因为每2个数为1组,所以每次要加2
  157.                         if(i==num)                                                                                        // 判断歌曲是否播放完了
  158.                         {
  159.                                 gPlayStatus=0;                                                                // 播放完了的话,则把播放状态改为暂停,否则会循环播放
  160.                         }
  161.                 }
  162.                
  163.                 if(Key9_P==0)                                                                                         // 下一曲
  164.                 {
  165.                         DelayMs(10);                                                                                // 消除按键按下的抖动
  166.                         while(!Key9_P);                                                                    // 等待按键释放
  167.                         DelayMs(10);                                                                                // 消除按键松开的抖动
  168.                         gSong++;                                                                                                // 把当前播放到第几首歌的变量gSong加1,即切到下一曲
  169.                         if(gSong>SONG)                                                                        // 如果gSong为SONG,说明到后面的尽头了,则转为第一首
  170.                                 gSong=1;
  171.                         break;        
  172.                 }                                
  173.         }
  174. }
  175. /*********************************************************/

  176. /*********************************************************************
  177.      : FlashLed1

  178. *********************************************************************/
  179. void FlashLed1(void)
  180. {
  181.          LED_PORT = 0x55;                        //
  182.          DelayMs(200);
  183.          
  184.          LED_PORT = 0xaa;                        //
  185. DelayMs(200);

  186. }

  187. /*********************************************************************
  188.       : FlashLed2
  189. *********************************************************************/
  190. void FlashLed2(void)
  191. {
  192.         unsigned char i = 0;

  193.         for (i=0; i<7; i++)
  194.         {
  195.                 LED_PORT  = (0xff & ~(1<<i));
  196.                 DelayMs(200);
  197.         }
  198. }
  199. /*********************************************************************
  200.       : FlashLed3
  201. *********************************************************************/
  202. void FlashLed3(void)
  203. {
  204.                  LED_PORT = 0xff;                        //
  205.          DelayMs(200);
  206.          
  207.          LED_PORT = 0x00;                        //
  208. DelayMs(200);
  209. }
  210. /*********************************************************************
  211.       : FlashLed4
  212. *********************************************************************/
  213. void FlashLed4(void)
  214. {
  215.         unsigned char i = 0;

  216.         for (i=0; i<7; i++)
  217.         {
  218.                 LED_PORT  =i;
  219.                 DelayMs(200);
  220.         }
  221. }
  222. /*********************************************************************
  223.       : FlashLed5
  224. *********************************************************************/
  225. void FlashLed5(void)
  226. {
  227.         unsigned char i = 0;

  228.         for (i=0; i<7; i++)
  229.         {
  230.                 LED_PORT  = (0xff & (1<<i));
  231.                 DelayMs(200);
  232.         }
  233. }
  234. /*********************************************************************
  235.       : FlashLed6
  236. *********************************************************************/
  237. void FlashLed6(void)
  238. {
  239.         unsigned char i = 0;

  240.         for (i=0; i<7; i++)
  241.         {
  242.                 LED_PORT  = (0xff & ~(1<<6-i));
  243.                 DelayMs(200);
  244.         }
  245. }
  246. /*********************************************************************
  247.       : FlashLed7
  248. *********************************************************************/
  249. void FlashLed7(void)
  250. {
  251.         LED_PORT = 0x0f;                        //
  252.          DelayMs(200);
  253.          
  254.          LED_PORT = 0xf0;                        //
  255. DelayMs(200);
  256. }
  257. void LED_PLAY(uchar num)
  258. {
  259.         switch(num)
  260.         {
  261.           case(0x01):FlashLed1();break;
  262.                 case(0x02):FlashLed2();break;
  263.                 case(0x03):FlashLed3();break;
  264.                 case(0x04):FlashLed4();break;
  265.                 case(0x05):FlashLed5();break;
  266.                 case(0x06):FlashLed6();break;
  267.                 case(0x07):FlashLed7();break;
  268.         }
  269. }

  270. /*********************************************************/
  271. // 定时器初始化函数
  272. /*********************************************************/
  273. void TimerInit()
  274. {
  275.         TMOD=1;                        // 定时器0,工作方式1
  276.         TH0=0;                        // 装定时器TH0的初值
  277.         TL0=0;                        // 装定时器TL0的初值
  278.         ET0=1;                        // 开启定时器0中断                  
  279.         EA=1;                                // 开启总中断
  280. }



  281. /*********************************************************/
  282. // 弹奏键扫描函数
  283. /*********************************************************/
  284. uchar KeyScanf()
  285. {
  286.         if(Key_Set1==0)          // 按键被按下  P2^3
  287.           yinquflag=1;    //音区1
  288.         if(Key_Set2==0)          // 按键被按下  P2^5
  289.           yinquflag=2;    //音区2
  290.         if(Key_Set3==0)          // 按键被按下  P2^6
  291.           yinquflag=3;    //音区3
  292.         if(Key1_P==0)                // 按键1被按下,返回1
  293.                 return 1;
  294.         if(Key2_P==0)                // 按键2被按下,返回2
  295.                 return 2;
  296.         if(Key3_P==0)         // 按键3被按下,返回3
  297.                 return 3;
  298.         if(Key4_P==0)         // 按键4被按下,返回4
  299.                 return 4;
  300.         if(Key5_P==0)         // 按键5被按下,返回5
  301.                 return 5;
  302.         if(Key6_P==0)                // 按键6被按下,返回6
  303.                 return 6;
  304.         if(Key7_P==0)                // 按键7被按下,返回7
  305.                 return 7;
  306.         // if(Key8_P==0)          // 按键8被按下,返回8
  307.         //         return 8;
  308.                
  309.         return 0;                          // 8个按键都没被按下,返回0
  310. }



  311. /*********************************************************/
  312. // 主函数,程序从这里开始执行
  313. /*********************************************************/        
  314. void main()
  315. {  
  316.         uchar i;                                                                // 循环变量
  317.         uchar ret;                                                        // 用于保存音调键函数的返回值
  318.         uchar count;                                                // 用于记录当前录制了多少个音调
  319.         uchar record[99]={0};                // 存储录制歌曲的数组

  320.         TimerInit();
  321.         gSong=0;                                                                // 上电默认第一首歌
  322.         gPlayStatus=0;                                        // 上电默认是0停止状态(1为播放状态)

  323.         while(1)
  324.         {
  325.                 if(gPlayStatus==1)                // 如果处于播放状态,则判断是哪一首歌曲需要播放
  326.                 {
  327.                         switch(gSong)                 
  328.                         {
  329.                                 case 1 : PlayMusic(Music1,sizeof(Music1)); break;
  330.                                 case 2 : PlayMusic(Music2,sizeof(Music2)); break;
  331.                                 case 3 : PlayMusic(Music3,sizeof(Music3)); break;
  332.                                 case 4 : PlayMusic(Music4,sizeof(Music4)); break;
  333.                                 default:                                               break;        
  334.                         }        
  335.                 }
  336.                
  337.                 /*播放内置的音乐*/
  338.                 if(Key9_P==0)                                        // 开始播放
  339.                 {
  340.                         DelayMs(10);                                // 消除按键按下的抖动
  341.                         while(!Key9_P);                        // 等待按键释放
  342.                         DelayMs(10);                                // 消除按键松开的抖动
  343.                         gSong++;                                                // 把当前播放到第几首歌的变量gSong加1,即切到下一曲
  344.                         if(gSong>SONG)                        // 如果gSong为SONG,说明到后面的尽头了,则转为第一首
  345.                                 gSong=1;
  346.                         gPlayStatus=1;                        // 播放状态改为1,即播放
  347.                         
  348.                 }
  349.                
  350.                 /*开始/停止 录制按键的处理*/
  351.                 if(Key10_P==0)
  352.                 {
  353.                         Led_P=~Led_P;                                                        // 录歌指示灯状态切换
  354.                         if(Led_P==0)                                                        // 如果是切换为录歌状态
  355.                         {
  356.                                 count=0;                                                           // 清零记录按键值计数,从新开始计数
  357.                         }        
  358.                         DelayMs(10);                                                        // 消除按键按下的抖动
  359.                         while(!Key10_P);                                        // 等待按键释放
  360.                         DelayMs(10);                                                        // 消除按键松开的抖动
  361.                 }
  362.                
  363.                 /*播放录制的音乐*/
  364.                 if(Key11_P==0)                                                
  365.                 {
  366.                         for(i=0;i<count;i++)
  367.                         {
  368.                                 PlayTone(record[i],2);        // 播放该音调
  369.                                 DelayMs(50);                                                // 每播放一个音调,停顿50毫秒
  370.                         }
  371.                         DelayMs(10);                                                        // 消除按键按下的抖动
  372.                         while(!Key11_P);                                        // 等待按键释放
  373.                         DelayMs(10);                                                        // 消除按键松开的抖动
  374.                 }
  375.                
  376.                 /* 8个弹奏按键的扫描 */                        
  377.                 ret=KeyScanf();                                                        // 获取8个按键的扫描结果

  378.                 if(ret!=0)                                                                        // 如果有按键按下去了
  379.                 {
  380.                         ledflag=ret;              //给流水灯赋值
  381.                         P3=(0xff)^ledflag;
  382.                         P0=ArrDig[(ret-1)%7];                        // 数码管显示当前音调值
  383.                         TH0 = ArrTH0[ret];                        // 装入定时器TH0的初值
  384.                         TL0 = ArrTL0[ret];                        // 装入定时器TL0的初值
  385.                         gTone=ret;
  386.                         if(Led_P==0)                                                  // 如果是录音状态,则把弹奏值记录下来
  387.                         {
  388.                                 record[count]=gTone;                // 记录当前弹奏的按键值
  389.                                 count++;                                                                // 准备记录下一个
  390.                         }
  391.                         TR0=1;                                                                                // 启动定时器,播放弹奏的音符
  392.                         DelayMs(20);                                                        // 去除按键按下的抖动
  393.                         while(KeyScanf());                                // 等待按键释放
  394.                         DelayMs(70);                                                        // 按键释放之后,再播放70毫秒,达到余音的效果
  395.                         TR0=0;                                                                                // 停止定时器
  396.                         P0=0xff;                                           // 关闭数码管显示
  397.                         P3=0xff;                                           // 关闭led
  398.                         Beep_P=1;                                                                        // 关闭定时器,停止弹奏音符的播放
  399.                 }        
  400.                 // LED_PLAY(ledflag);
  401.         }
  402. }

  403.         

  404. /*********************************************************/
  405. // 功能:定时器0中断处理函数
  406. /*********************************************************/                  
  407. void time0() interrupt 1
  408. {
  409.         Beep_P=!Beep_P;                                // 将控制扬声器的管脚取反
  410.         if(yinquflag ==1)
  411.         {
  412.                         TH0=ArrTH0[gTone];                // 重装定时器TH0的初值
  413.             TL0=ArrTL0[gTone];                // 重装定时器TL0的初值        
  414.   }
  415.         else if(yinquflag ==2)
  416.         {
  417.                         TH0=ArrTH0[gTone+5];                // 重装定时器TH0的初值
  418.             TL0=ArrTL0[gTone+5];                // 重装定时器TL0的初值        
  419.   }
  420.         else if(yinquflag ==3)
  421.         {
  422.                 TH0=ArrTH0[gTone+10];                // 重装定时器TH0的初值
  423.           TL0=ArrTL0[gTone+10];                // 重装定时器TL0的初值        
  424.   }
  425. }
复制代码

全部资料51hei下载地址:
电子琴终结版.rar (108.31 KB, 下载次数: 72)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表