找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
楼主: zxp0751909113
收起左侧

51单片机8音键电子琴设计(带仿真 AD原理图与PCB代码开源)

  [复制链接]
ID:227785 发表于 2017-8-15 19:53 | 显示全部楼层 |阅读模式
包含Proteus仿真,原理图,PCB及源程序

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png

8音键电子琴介绍:

          该设计采用AT89C52(AT89C52数据手册)单片机作为主控制芯片,外接灯光闪烁功能和8音调键。共有8个音节和4个功能按键。可播放内置乐曲,可弹奏录音,采用24C02(24C02数据手册)芯片作为EEPROM存储,掉电不掉内容,LM386(LM386数据手册)功放模块外接扬声器。

具体功能介绍:

    8个弹奏键,具有很强的娱乐性。
    独创--弹奏录音功能 能录音,能回放,听起来更惬意。
    内置多首音乐。
    4个功能按键设计,PLAY(播放)NEXT(下一首),PRE(上一首),STOP(停止)按键。
    5V电源转接PIN,供电稳定,方便实用。
    采用LM386功放和专用音乐喇叭,声音更柔和动听,不再是蜂鸣器的刺耳啸叫。

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件):
0.png 0.png 0.png

元件清单:
主机元件清单
名称    参数    数量
电阻    470,1K、10K、10欧    若干
电位器    10K    1
发光二极管        9
电源接口        1
电解电容    10uf    1
电解电容    250uf    1
独石电容    104    1
瓷片电容    30pf    2
按键        13
晶振    12.00M    1
排针        若干
AT89S52单片机        1
AT24C08        1
扬声器    0.5W 8欧    1
LM386        1


单片机源程序如下:
  1. /**************************************************************
  2. 程序名称:模拟电子琴
  3. **************************************************************/
  4. #include<reg52.h>                                     //定义头文件
  5. #define uchar unsigned char                        //宏定义
  6. #define led P0                                        //定义LED等位P0口
  7. #define sw_port P1                                //中间变量。。。使按键和led对应
  8. sbit buzzer=P2^7;                                //扬声器管脚
  9. sbit key1=P3^2;                                        //播放音乐与弹奏歌曲转换
  10. sbit key3=P3^4;                                        //掉电存储按键
  11. sbit key4=P3^5;                 //播放掉电存储的歌曲                                         
  12. sbit keybofang=P3^3;                        //播放刚才弹奏的歌曲
  13. sbit key7=P3^0;                                        //音调键。。。 和  歌曲键
  14. sbit key8=P3^1;                                        //音调键。。。 和  歌曲键
  15. sbit key6=P1^7;
  16. sbit key5=P1^6;                                   
  17. sbit sda=P1^1;                                              //24c02数据线  
  18. sbit scl=P1^0;                                        //24c02时钟线
  19. uchar keyd,i,keys,b;                                  //定义变量
  20. uchar tone_H;                                        //定义变量
  21. uchar tone_L;                                        //定义变量
  22. void beat_125(unsigned char);                        //声明函数
  23. uchar code beat1[]={16,8,8,8,8,4,4,16,8,4,4,8,4,4,4,        //歌曲1节拍
  24. 4,4,4,16,16,8,8,4,4,12,8,16,16,8,4,4,4,4,16};
  25. uchar code song1[]={6,5,3,5,7,6,5,6,3,5,6,5,3,                //歌曲1简谱
  26. 2,1,6,5,3,2,2,3,5,5,6,3,2,1,5,3,2,1,6,1,1,15};

  27. uchar code beat2[]={7,7,7, 7,8,9, 1,2,3, 6,2,4, 4,4,4, 12,         //歌曲二节拍
  28. 8,2,2, 4,4,4, 8,2,2, 4,4,4, 2,2,4,4, 12,};
  29. uchar code song2[]={1,2,8, 8,5,1, 3,3,3, 5,4,3,                //歌曲二简谱
  30. 5,4,3, 2, 2,1,0, 1,2,3, 4,3,2, 3,4,5, 5,4,3, 2,1,15};

  31. uchar code beat4[]={4,4,4, 6,2,4, 4,4,4, 6,2,4, 4,4,4, 12,
  32. 8,2,2, 4,4,4, 8,2,2, 4,4,4, 2,2,4,4, 12,};
  33. uchar code song4[]={1,1,1, 3,2,1, 3,3,3, 5,4,3,
  34. 5,4,3, 2, 2,1,0, 1,2,3, 4,3,2, 3,4,5, 5,4,3, 2,1, 15};

  35. uchar code tone[]={115,102,91,86,77,68,61,57};                //歌曲音调
  36. unsigned int code tone1[]={1012,956,852,759,716,638,568,506,478,426,379,531,10}; //歌曲音调
  37. uchar song3[43];                                              //定义空数组
  38. void play(uchar*,uchar*);                                  //演奏歌曲函数
  39. void delay8um(uchar);                                          //第一8um延时函数
  40. void sound(uchar);                                        //弹奏发声函数
  41. /*******************************************
  42. 函数功能:节拍的延时的基本单位,用于24c08简单延时
  43. ******************************************/                                         
  44. void delay()                                                //简单延时函数
  45. {;;}
  46. /*******************************************
  47. 函数功能:节拍的延时的基本单位,延时1ms
  48. ******************************************/
  49. void delay1ms(uchar x)                                          //1um延时函数
  50. {
  51.         uchar j;
  52.         while(x--)
  53.                 for(j=120;j>0;j--);
  54. }
  55. /**************************************************************
  56. 函数功能:24c02驱动程序      用IIC总线进行传输
  57. **************************************************************/
  58. void init_c02()                                                //24c02初始化
  59. {
  60.         sda=1;
  61.         delay();
  62.         scl=1;
  63.         delay();
  64. }
  65. void start_c02()                                             //24c02的启动信号
  66. {
  67.         scl=1;
  68.         delay();         
  69.         sda=1;         
  70.         delay();
  71.         sda=0;
  72.         delay();

  73. }
  74. void stop_c02()                                                   //24c02停止信号
  75. {
  76.         sda=0;
  77.         delay();
  78.         scl=1;
  79.         delay();
  80.         sda=1;
  81.         delay();
  82. }
  83. void response_c02()                                        //24c02的应答信号
  84. {
  85.         uchar i;
  86.         scl=1;
  87.         delay();
  88.         while((sda==1)&&(i<250))i++;
  89.         scl=0;
  90.         delay();
  91. }
  92. void write_c02byte(uchar date)                                    //对24c02写一个字节
  93. {
  94.         uchar i,temp;
  95.         temp=date;
  96.         for(i=0;i<8;i++)
  97.         {        
  98.                 temp=temp<<1;
  99.                 scl=0;
  100.                 delay();
  101.                 sda=CY;
  102.                 delay();
  103.                 scl=1;
  104.                 delay();
  105.         }
  106.         scl=0;
  107.         delay();
  108.         sda=1;
  109.         delay();
  110. }
  111. uchar read_c02byte()                                        //对24c02读一个字节
  112. {
  113.          uchar i,k;
  114.          scl=0;
  115.          delay();
  116.          sda=1;
  117.          delay();
  118.          for(i=0;i<8;i++)
  119.          {
  120.                  scl=1;
  121.                 delay();
  122.                 k=(k<<1)|sda;
  123.                 scl=0;
  124.                 delay();
  125.         }
  126.         return k;
  127. }
  128. void write_addc02(uchar address,uchar date)                //对24c02写一个数据        
  129. {
  130.         start_c02();
  131.          write_c02byte(0xa0);
  132.         response_c02();
  133.         write_c02byte(address);
  134.         response_c02();
  135.         write_c02byte(date);
  136.         response_c02();
  137.         stop_c02();
  138. }
  139. uchar read_addc02(uchar address)                        //从24c02读一个数据
  140. {
  141.         uchar date;
  142.         start_c02();
  143.         write_c02byte(0xa0);
  144.         response_c02();
  145.         write_c02byte(address);
  146.         response_c02();
  147.         start_c02();        
  148.         write_c02byte(0xa1);
  149.         response_c02();
  150.         date=read_c02byte();
  151. //        response_c02;
  152.         stop_c02();
  153.         return date;
  154. }
  155. /**************************************************************
  156. 函数功能:主函数。。。。。。。。。。。。
  157. **************************************************************/  
  158. void main()                                                //主函数
  159. {        
  160.         uchar yd,temp,jj,tt;                                //定义变量
  161.         uchar t1,i;                                        //定义变量
  162.         t1=0;                                                //初始化 t1
  163.         yd=0;                            //初始化t2
  164.         buzzer=1;                                         //初始化蜂鸣器
  165.         EA=1;                                                //打开定时总中断
  166.         TMOD=0x01;                                        //设置定时器模式  定时器0工作在方式1        
  167.         ET0=1;                                                //打开定时器0中断
  168.         while(1)                                        //主循环
  169.         {
  170.                 led=0x3c;
  171.                 sw_port=0xff;
  172.                 keys=~sw_port;                                //将led与按键结合起来
  173.                 switch(keys)                                //进入键盘选择
  174.                 {
  175.                         case 0x04:sound(0);temp=1;yd=0;break;         //如果键盘1被按下发音do,同时设置标志temp,将数字计入yd
  176.                         case 0x08:sound(1);temp=1;yd=1;break;         //如果键盘2被按下发音ruai,同时设置标志temp,将数字计入yd
  177.                         case 0x10:sound(2);temp=1;yd=2;break;         //如果键盘3被按下发音mi,同时设置标志temp,将数字计入yd
  178.                     case 0x20:sound(3);temp=1;yd=3;break;         //如果键盘4被按下发音fa,同时设置标志temp,将数字计入yd

  179.                 }
  180.                 if(key5==0)                                //如果键盘5被按下发音la,同时设置标志temp,将数字计入yd
  181.                 {
  182.                                 while(!key5)                // 松手检测
  183.                                  sound(4);
  184.                                 temp=1;yd=4;        
  185.                 }
  186.                 if(key6==0)                                //如果键盘6被按下发音xi,同时设置标志temp,将数字计入yd
  187.                 {
  188.                                 while(!key6)                // 松手检测
  189.                                  sound(5);
  190.                                 temp=1;yd=5;        
  191.                 }
  192.                 if(key7==0)                                //如果键盘7被按下发音xi,同时设置标志temp,将数字计入yd
  193.                 {
  194.                                 while(!key7)                // 松手检测
  195.                                  sound(6);
  196.                                 temp=1;yd=6;        
  197.                 }
  198.                 if(key8==0)                                //如果键盘8被按下发音高音do,同时设置标志temp,将数字计入yd
  199.                 {
  200.                                 while(!key8)                 //松手检测
  201.                                  sound(7);                //播放高音do。。
  202.                                 temp=1;yd=7;
  203.                 }
  204.                 if(temp==1)                                //标志位,如果标志位为1,则说明有按键被按下
  205.                 {
  206.                         
  207.                         temp=0;                                //将标识位归零
  208.                         song3[t1++]=yd;                //将数据存入song3[]数组
  209.                 }

  210.                 if(key3==0)                                //将数据存入24c02 ,掉电存储按键
  211.                 {
  212.                         delay1ms(10);
  213.                         if(key3==0)                        //检测是否key3被按下
  214.                         {        
  215.                                 P0=0;                        //如果被按下,将led打开
  216.                                 while(!key3);                 //松手检测
  217.                                 song3[t1++]=30;        
  218.                                 init_c02();                //初始化24c02
  219.                                         for(i=0;i<40;)        //进入循环
  220.                                         {
  221.                                                  write_addc02(i,song3[i++]);        //将数据依次写入24c02
  222.                                                  delay1ms(10);                        //延时
  223.                                         }
  224.                                      P0=1;                                                //led关闭
  225.                         }
  226.                 }
  227.                 if(key4==0)                                //读取24c02中的数据,掉电播放
  228.                 {
  229.                         delay1ms(10);
  230.                         if(key4==0)
  231.                         {                                //检测是否有键被按下
  232.                                 
  233.                                 while(!key4);                //松手检测
  234.                                 init_c02();                 //初始化
  235.                                 P0=0;                        //将led打开                                       
  236.                                 tt=1;                        //将tt初值设为0
  237.                                 while(read_addc02(tt)!=30)                        //进入while循环
  238.                                 {
  239.                                         jj=read_addc02(tt++);
  240.                                         tone_H=(65536-tone1[jj])/256;                //设定初值
  241.                                         tone_L=(65536-tone1[jj])%256;                //设定初值                                 
  242.                                      TH0=tone_H;                                //赋值TH0高八位
  243.                                          TL0=tone_L;                                //赋值TL0低八位
  244.                                          TR0=1;                                            //打开定时器
  245.                                          beat_125(3);                                 //延时
  246.                                          TR0=0;
  247.                                          beat_125(4);                                //关闭定时器
  248.                                 }
  249.                                 P0=1;                                                //关闭led
  250.             }
  251.                 }

  252.                 if(keybofang==0)
  253.                 {
  254.                         while(!keybofang);                                        //检测回放键是否被按下
  255.                         song3[t1++]=30;
  256.                    //        t1=0;
  257.                         while(song3[i]!=30)                                        //进入while循环。
  258.                         {
  259.                                   tone_H=(65536-tone1[song3[i]])/256;
  260.                                  tone_L=(65536-tone1[song3[i]])%256;
  261.                                  TH0=tone_H;
  262.                                  TL0=tone_L;
  263.                                  TR0=1;                                                //开启定时器
  264.                              beat_125(3);                                                                                                   
  265.                                  TR0=0;                                                //关闭定时器
  266.                                  i++;
  267.                                  beat_125(4);                                        //将i值加一                                                        
  268.                     }                                                                                                  
  269.                 }
  270.                 if(key1==0)
  271.                 {
  272.                         delay1ms(10);
  273.                         if(key1==0)                                                //检测key1是否被按下
  274.                         {        
  275.                                 while(!key1);
  276.                                 P0=0;                                                //关闭led
  277.                                 while(key1)                                        //进入循环
  278.                                 {               
  279.                                    if(key7==0)                                           //检测key7是否被按下
  280.                                         {
  281.                                                 delay1ms(10);
  282.                                                 if(key7==0)
  283.                                                 {
  284.                                                         P0=0xaa;                //设置led灯亮个数
  285.                                                         while(!key7);                //等待释放
  286.                                                         play(song1,beat1);        //演奏歌曲1
  287.                                                         P0=0xff;                //关闭led
  288.                                                 }
  289.                                         }
  290.                                         if(key8==0)                                //检测是否key8键被按下
  291.                                         {
  292.                                                 delay1ms(10);
  293.                                                 if(key8==0)
  294.                                                 {
  295.                                                         P0=0xaa;                //设置led灯亮
  296.                                                         while(!key8);                //松手检测
  297.                                                         play(song2,beat2);        //播放歌曲2
  298.                                                         P0=0xff;                //关闭led
  299.                                                 }                        
  300.                                         }
  301.                                         if(key6==0)                                //检测是否key6键被按下
  302.                                         {
  303.                                                 delay1ms(10);
  304.                                                 if(key6==0)
  305.                                                 {
  306.                                                         P0=0xaa;                //设置led灯亮
  307.                                                         while(!key6);                //松手检测
  308.                                                         play(song4,beat4);        //播放歌曲4
  309.                                                         P0=0xff;                //关闭led
  310.                                                 }                        
  311.                                         }  
  312.                                 }
  313.                                         while(!key1);                                //检测key1是否被按下
  314.                                         P0=1;                                        //如果被按下。退出该函数。。并关闭led
  315.                                 
  316.                         }
  317.                 }
  318.         
  319.         }
  320. }
  321. /**************************************************************
  322. 函数功能:从数组中播放歌曲
  323. **************************************************************/
  324. void play(uchar*song,uchar*beat)                        //播放歌曲函数
  325. {
  326.          i=0;                                                //设置初始值
  327.          while(song[i]!=15)                                //  进入循环函数
  328.          {
  329.                   tone_H=(65536-tone1[song[i]])/256;        //定义初值
  330.                  tone_L=(65536-tone1[song[i]])%256;        //定义初值
  331.                  TH0=tone_H;                                //赋值
  332.                  TL0=tone_L;                                 //赋值
  333.                  TR0=1;                                        //打开定时器0
  334.                  beat_125(beat[i]);                        //读取节拍函数
  335.                  i++;                                        //自加
  336.                  TR0=0;                                        //关闭led
  337.          }
  338. }
  339. /**************************************************************
  340. ……………………

  341. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
附件内容包括:
整个电路设计原理图和PCB源文件,用AD软件打开;
源程序;
仿真电路,用proteus软件打开;
BOM表;

我这个目前目前问题还很多,研究了几天,也没有解决,仿真也没有效果,求大神帮帮忙看看我这电路和程序哪里错了?
错误文件: 基于51单片机8音键电子琴DIY制作(完整设计项目开源).zip (114.57 KB, 下载次数: 475)

评分

参与人数 3黑币 +60 收起 理由
qjk + 5 共享资料的黑币奖励!
syzxsss + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:246588 发表于 2017-11-13 19:37 | 显示全部楼层
仿真后没声音?
回复

使用道具 举报

ID:259588 发表于 2017-12-10 09:41 来自手机 | 显示全部楼层
对,都没声音
回复

使用道具 举报

ID:64089 发表于 2017-12-12 11:00 | 显示全部楼层
有点意思,可以作为初学者练手的资料
回复

使用道具 举报

ID:313541 发表于 2018-4-23 09:31 | 显示全部楼层
多谢分享
回复

使用道具 举报

ID:313521 发表于 2018-4-23 09:32 | 显示全部楼层
正需要,谢谢分享
回复

使用道具 举报

ID:317261 发表于 2018-4-26 19:19 | 显示全部楼层
给力 好文档
回复

使用道具 举报

ID:308555 发表于 2018-5-9 18:37 来自手机 | 显示全部楼层
470是贴片电阻吗
回复

使用道具 举报

ID:308555 发表于 2018-5-12 21:47 来自手机 | 显示全部楼层
我的灯都亮,可是扬声器没有声音,求解答
回复

使用道具 举报

ID:242960 发表于 2018-5-23 20:32 | 显示全部楼层
大大 为啥仿真图没出来啊 按键没有反应 源代码运行无错 且导入芯片了
回复

使用道具 举报

ID:242960 发表于 2018-5-23 21:53 | 显示全部楼层
大大 问一下 为啥你的原理图上没有喇叭??没有喇叭 怎么出声音?
回复

使用道具 举报

ID:87877 发表于 2018-9-18 19:39 | 显示全部楼层
不错!谢分享。。。。。。
回复

使用道具 举报

ID:422502 发表于 2018-11-7 17:52 | 显示全部楼层
多谢分享.大佬加油
回复

使用道具 举报

ID:426477 发表于 2018-11-14 16:26 | 显示全部楼层
ok,很好
回复

使用道具 举报

ID:426970 发表于 2018-11-15 11:55 来自手机 | 显示全部楼层
还有pcb图,很良心,谢谢
回复

使用道具 举报

ID:428533 发表于 2018-11-30 23:45 来自手机 | 显示全部楼层
为什么灯凉了  有电流声  没有音乐声呢?
回复

使用道具 举报

ID:428533 发表于 2018-11-30 23:47 来自手机 | 显示全部楼层
为什么板子做出来  灯凉了  蜂鸣器只有电流声  听不到音乐声呢?
回复

使用道具 举报

ID:434742 发表于 2018-12-2 14:41 | 显示全部楼层
你好,请问一下这个程序为啥不响啊
回复

使用道具 举报

ID:451931 发表于 2018-12-22 10:28 | 显示全部楼层
没有声音是怎么回事?
回复

使用道具 举报

ID:441217 发表于 2018-12-24 23:12 | 显示全部楼层
仿真图喇叭不响,按键也没有反应
回复

使用道具 举报

ID:411747 发表于 2019-3-2 16:19 | 显示全部楼层
很棒的资料,适合初学者
回复

使用道具 举报

ID:441855 发表于 2019-3-7 09:24 | 显示全部楼层
没音乐吗?但是很适合初学者的资料
回复

使用道具 举报

ID:471889 发表于 2019-3-10 09:30 | 显示全部楼层
很好的作品,谢谢分享

评分

参与人数 1黑币 +9 收起 理由
正规007 + 9 很给力!

查看全部评分

回复

使用道具 举报

ID:481253 发表于 2019-3-18 15:19 | 显示全部楼层
jiangqianjiangq 发表于 2018-12-24 23:12
仿真图喇叭不响,按键也没有反应

我也是,仿真都不行,按键不行,灯也不亮。
回复

使用道具 举报

ID:497882 发表于 2019-4-1 18:42 | 显示全部楼层
仿真图的喇叭不响,按键没反应。
回复

使用道具 举报

ID:445655 发表于 2019-5-15 01:43 | 显示全部楼层
为啥仿真图按键不管用
回复

使用道具 举报

ID:531751 发表于 2019-5-17 12:47 | 显示全部楼层
能说一下怎么操作吗?好像没有声音?
回复

使用道具 举报

ID:555349 发表于 2019-6-5 09:58 | 显示全部楼层
haojia 发表于 2017-11-13 19:37
仿真后没声音?

程序对了吗?
回复

使用道具 举报

ID:581063 发表于 2019-7-9 16:51 | 显示全部楼层

麻烦问下这个帖子上的代码是不是不全啊?还差多少啊,谢谢
回复

使用道具 举报

ID:89286 发表于 2019-7-10 08:24 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:657933 发表于 2019-12-26 17:46 | 显示全部楼层
还是很可以的,感谢楼主分享
回复

使用道具 举报

ID:657933 发表于 2019-12-27 22:33 | 显示全部楼层
代码和PCB是不是不全啊??
回复

使用道具 举报

ID:788495 发表于 2020-6-27 09:09 | 显示全部楼层
兄弟,这没喇叭鸭...
回复

使用道具 举报

ID:759682 发表于 2020-7-15 18:03 | 显示全部楼层
仿真成功了吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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