找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机简易音乐播放器Proteus仿真程序

[复制链接]
跳转到指定楼层
楼主
实现简易播放旋律音乐
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


简易音乐播放器的工作原理

简易音乐播放器是通过MCU产生特定频率的信号,以达到控制蜂鸣器发出不同的声音的目的。因此,简易交通灯包括MCU最小系统电路,蜂鸣器驱动电路,按键控制电路。基本原理如图2.1所示。


图2.1 简易音乐播放器原理框架
由图2.1可以看出,按键控制电路向MCU最小系统发送控制信号,MCU最小系统发出不同频率的信号控制蜂鸣器驱动电路发出声音,达到播放音乐的目的。

2.3 蜂鸣器的的选择

图2.4 无源蜂鸣器
蜂鸣器分为有源蜂鸣器和无源蜂鸣器两种,有源和无源指的是“震荡源”而不是“电源”,有源蜂鸣器的内部含有震荡源,两个引脚接入电源就会直接发出声音,使用起来简单方便,但由于内部震荡源确定,只能发出单一的声音,所以我们这里选用无源振荡器;无缘振荡器内部不含震荡源,使用的时候必须在引脚上加入震荡的方波,驱动起来比较复杂,但是无源蜂鸣器可以根据方波频率的变化发出不同的声音,非常适合我们做简易音乐播放器的发声装置。

2.4 三极管驱动蜂鸣器

图2.5 NPN三极管
无源蜂鸣器的驱动方式有很多种,常见的有使用PNP三极管驱动、NPN三极管驱动、ULN2003D芯片驱动。总而言之,单片机自身的驱动电流无法驱动蜂鸣器发声,需要一个放大器件进行驱动。
这里选用NPN三极管进行驱动,因为NPN三极管常见,成本低、稳定性好,相对于ULN2003D来说性价比更好,更符合工程实际。

2.5 LCD1602显示电路
LCD1602的8根数据线和3根控制线E,RS和R/W与单片机相连后即可正常工作。一般应用中只须往LCD1602中写入命令和数据,因此,可将LCD1602的R/W读/写选择控制端直接接地,这样可节省1根数据线。VO引脚是液晶对比度调试端,通常连接一个10kΩ的电位器即可实现对比度的调整;也可采用将一个适当大小的电阻从该引脚接地的方法进行调整,不过电阻的大小应通过调试决定。


第三章 电路分析与参数计算
图3.1 STC89C52单片机复位电路
8051系列单片机的ALE及/PSEN两引脚输出高电平,RST引脚高电平到时,单片机复位。若直接由启动瞬间产生,则为启动复位,若通过按动按钮产生高电平复位称手动复位。如图3.1所示,上电时,接通电源,电容器C相当于瞬间短路,+5V加到了RST/VPD端,该高电平使8051全机复位。

3.2 蜂鸣器驱动电路

图3.2 蜂鸣器驱动电路
蜂鸣器的驱动电路,如图3.2所示。由于单片机1/0口的驱动电流仅有100~200
uA,远远小于驱动蜂鸣器的电流,故用三极管来扩流,这里用的是2    N3417(NPN)。由原理图可知,单片机的P2.6端口出现高电平时,三极管导通,从而电流由VCC经三极管再经蜂鸣器到达GND,这样蜂鸣器就会发声;相反,若D5为低电平,则三极管截止,蜂鸣器中没有电流,那么肯定就不发声。
3.3 按键控制电路

图3.3 按键控制电路
简易音乐播放器的按键控制电路由三个按键组成,分别接在单片机的P1.0-P1.2口,单片机IO口在默认情况下为高电平,当按键按下后引脚接地,单片机IO口变为低电平。单片机由此判断哪个按键按下。
MUSIC1:音乐一播放按键,按键按下后,简易音乐播放器播放第一首音乐。
MUSIC2:音乐二播放按键,按键按下后,简易音乐播放器播放第二首音乐。
PAUSE/CONTINUE:音乐暂停/播放按键,在音乐播放时,可以通过此按键控制音乐的播放与暂停。

第四章 程序设计与仿真调试

4.1 程序设计
4.1.1 简易音乐播放器总体流程
  1.系统上电后,等待音乐选择。
  2.音乐播放时可以暂停和切换歌曲。


仿真中遇到的问题
1.简易音乐播放器仿真时,无源蜂鸣器元件BUZZTON无法发出声音。

排查过程:首先检查了蜂鸣器驱动电路,元件是否选择正确,电路是否连接正确。然后检查其他硬件电路是否正常,最后检查程序是否正确。
原因与改进办法:在Proteus8.6版本中元件无源蜂鸣器BUZZTON不支持仿真,无论如何都是无法发出声音的,故使用无源蜂鸣器SOUNDER代替。

简易音乐播放器共有三个部分组成。第一个部分为STC89C52最小系统。最小系统控制引脚输出频率变化的方波,驱动无源蜂鸣器播放音乐。
第二部分是无源蜂鸣器驱动电路,因为单片机IO口本身驱动电流及其微小,无法直接驱动无源蜂鸣器,所以使用了一个NPN三极管放大电流,此部分也可以使用PNP型三极管或者ULN2003D驱动芯片。
第三部分是按键控制电路,三个按键分别控制播放两首音乐和控制音乐的播放和暂停。

单片机源程序如下:
  1. #include "reg52.h"   
  2. #include "string.h"   

  3. #define uint8     unsigned char
  4. #define uint16   unsigned short int

  5. #define SETMODE  0x38  //16*2显示,5*7点阵,8位数据接口
  6. #define DISOPEN  0x0C  //显示开,不显示光标,光标不闪烁
  7. #define DISMODE  0x06  //读写字符后地址加1,屏显不移动
  8. #define SETADDR  0x80  //设置数据地址指针初始值
  9. #define CLEAR  0x01  //清屏,数据指针清零
  10. #define RET  0x02  //回车,数据指针清零
  11. #define PORT  P0  //I/O口

  12. sbit RS = P2^6;
  13. sbit RW = P2^5;
  14. sbit E = P2^7;
  15. sbit key_stop = P3^0;//暂停按键
  16. sbit key_play = P3^1;//播放
  17. sbit key_next = P3^2;//下一首按键
  18. sbit key_last = P3^3;//上一首按键

  19. sbit Beep =  P1^5;

  20. uint8 code MUSIC1_NAME[]="MUSIC1";
  21. uint8 code MUSIC1_lyric[]="Bells on bob.tail ring";
  22. uint8 code MUSIC2_NAME[]="MUSIC2";
  23. uint8 code MUSIC2_lyric[]="Happy birthday to you!";
  24. uint8 code MUSIC3_NAME[]="MUSIC3";
  25. uint8 code MUSIC3_lyric[]="Two tigers,Two tigers";

  26. uint8 code string_stop[]="now stop................";



  27. uint8 music_cacah=0;//记录当前音乐曲目

  28. uint8 flag_music = 1;//音乐曲目标志
  29. uint8 flag_stop=1;//音乐播放/暂停标志

  30. unsigned char p,m;   //m为频率常数变量   
  31. unsigned char i=0;  



  32. unsigned char n=0;  //n为节拍常数变量   
  33. unsigned char code MUSIC1[] ={0xff,//Jing Bells
  34.                     0x26,0x20,0x18,0x20,0x19,0x20,0x1c,0x20,0x26,0x40,0x60,0x10,0x26,0x20,
  35.                     0x26,0x20,0x18,0x20,0x19,0x20,0x1c,0x20,0x24,0x40,0x60,0x10,0x24,0x20,
  36.                     0x18,0x20,0x19,0x20,0x13,0x20,0x13,0x20,0x13,0x20,0x13,0x20,0x12,0x20,
  37.                     0x13,0x20,0x15,0x20,0x19,0x20,0x1c,0x20,0x00,
  38.                    };
  39. unsigned char code MUSIC2[] ={0xff,//happy birthday
  40.                     0x26,0x20,0x26,0x20,0x24,0x40,0x26,0x40,0x1c,0x40,0x20,0x80,0x26,0x20,
  41.                     0x26,0x20,0x24,0x40,0x26,0x40,0x19,0x40,0x1c,0x80,0x26,0x20,0x26,0x20,
  42.                     0x13,0x40,0x18,0x40,0x1c,0x40,0x20,0x40,0x12,0x40,0x15,0x20,0x15,0x20,
  43.                     0x18,0x40,0x1c,0x40,0x19,0x40,0x18,0x80,0x26,0x20,0x26,0x20,0x18,0x40,
  44.                     0x1c,0x40,0x19,0x40,0x18,0x80,0x26,0x20,0x26,0x20,0x24,0x80,0x00,
  45.                    };
  46. unsigned char code MUSIC3[] ={0xff,//Two tigers
  47.                     0x39,0x40,0x33,0x40,0x30,0x40,0x39,0x40,0x39,0x40,0x33,0x40,0x30,0x40,
  48.                     0x39,0x40,0x30,0x40,0x2b,0x40,0x26,0x80,0x30,0x40,0x2b,0x40,0x26,0x80,
  49.                     0x26,0x10,0x24,0x30,0x26,0x10,0x2b,0x30,0x30,0x40,0x39,0x40,0x26,0x10,
  50.                     0x24,0x30,0x26,0x10,0x24,0x30,0x26,0x10,0x2b,0x30,0x30,0x40,0x39,0x40,
  51.                     0x39,0x40,0x26,0x40,0x39,0x80,0x39,0x40,0x26,0x40,0x39,0x80,0x00,
  52.                    };


  53. void Int1Init()
  54. {
  55.         TMOD&=0x0f;   
  56.   TMOD|=0x01;   
  57.   TH0=0xd8;TL0=0xef;  
  58.         EA=1;
  59.   ET0=1;
  60. }

  61. void delayms (unsigned char m)   //控制频率延时   
  62. {   
  63. unsigned i=3*m;   
  64. while(--i);   
  65. }  

  66. void delaymsms(unsigned char a)  //豪秒延时子程序   
  67. {   
  68.   while(--a);                  
  69. }  
  70. void Write1602_Com(uint8 com)
  71. {
  72.     E=0;
  73.     RS=0;  //命令
  74.     delayms(50);  //延时
  75.     RW=0;  //写
  76.     delayms(50);
  77.     PORT=com;  //端口赋值
  78.     delayms(50);
  79.     E=1;  //高脉冲
  80.     delayms(50);
  81.     E=0;
  82. }

  83. void Write1602_Dat(uint8 dat)
  84. {
  85.     E=0;
  86.     RS=1;  //数据
  87.     delayms(50);  //延时
  88.     RW=0;  //写
  89.     delayms(50);
  90.     PORT=dat;  //端口赋值
  91.     delayms(50);
  92.     E=1;  //高脉冲
  93.     delayms(50);
  94.     E=0;
  95. }

  96. void Init1602(void)
  97. {
  98.     Write1602_Com(SETMODE);  //模式设置
  99.     delayms(500);
  100.     Write1602_Com(DISOPEN);  //显示设置
  101.     delayms(500);
  102.     Write1602_Com(DISMODE);  //显示模式
  103.     delayms(500);
  104.     Write1602_Com(CLEAR);  //清屏
  105.     delayms(500);
  106. }

  107. void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf)
  108. {
  109.     uint8 i;
  110.     Write1602_Com(addr);
  111.     for(i=0;i<length;i++)
  112.     {
  113.        Write1602_Dat(pbuf[i]);
  114.     }
  115. }

  116. void scanf()
  117. {
  118.         if(key_stop == 0)
  119.         {
  120.                 delaymsms(10);//消抖
  121.                 flag_stop = 0;
  122.                 while(key_stop==0);//等待按键弹起
  123.         }
  124.         if(key_next == 0)
  125.         {
  126.                 delaymsms(10);//消抖
  127.                 flag_stop = 0;
  128.                 flag_music++;
  129.                 while(key_next==0);//等待按键弹起
  130.         }
  131.         if(key_last == 0)
  132.         {
  133.                 delaymsms(10);//消抖
  134.                 flag_stop = 0;
  135.                 flag_music--;
  136.                 while(key_last==0);//等待按键弹起
  137.         }
  138.        
  139.         if(flag_music==0)//1-8循环切歌
  140.                 flag_music=3;
  141.         if(flag_music==4)
  142.                 flag_music=1;
  143. }

  144. void music_play(uint8 ur[])
  145. {
  146.         music_cacah = flag_music;
  147.         i = 0;
  148. play:   
  149.    while(1)   
  150.     {   
  151.     a:
  152.                         if(flag_stop==0)//音乐暂停
  153.                                 {
  154.                                         if(flag_music != music_cacah)//如果播放途中切换了曲目,跳出当前播放
  155.                                         {
  156.                                                 flag_stop=1;
  157.                                                 break;
  158.                                         }
  159.                                         else
  160.                                         {
  161.                                                 Write1602_Str(0x80+0x40,strlen(string_stop),string_stop);  //"stoping..."
  162.                                                 while(1)//等待音乐播放
  163.                                                 {
  164.                                                         scanf();
  165.                                                         if(key_play==0||flag_music != music_cacah)//按下播放键
  166.                                                         {
  167.                                                                 flag_stop=1;
  168.                                                                 break;
  169.                                                         }
  170.                                                 }
  171.                                                 if(flag_music != music_cacah)//如果暂停途中切换了曲目,跳出当前播放
  172.                                                 {
  173.                                                         flag_stop=1;
  174.                                                         break;
  175.                                                 }
  176.                                         }
  177.                                 }
  178.                          p=ur[i];   
  179.        if(p==0x00)       { i=0, delaymsms(1000); goto play;}     //如果碰到结束符,延时1秒,回到开始再来一遍   
  180.        else if(p==0xff)  { i=i+1;delaymsms(100),TR0=0; goto a;}  //若碰到休止符,延时100ms,继续取下一音符   
  181.             else         {m=ur[i++], n=ur[i++];}  //取频率常数 和 节拍常数   
  182.              TR0=1;                                             //开定时器1   
  183.        while(n!=0) Beep=~Beep,delayms(m);                         //等待节拍完成  
  184.        TR0=0;                                             //关定时器1   
  185.     }
  186. }



  187. void main()
  188. {
  189.           Int1Init();//定时器中断1初始化

  190.                 Init1602();  //初始化1602
  191.           Write1602_Str(0x80+0x40,strlen(string_stop),string_stop);  //"stop"

  192.     while(1)
  193. ……………………

  194. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

仿真代码与word资料51hei附件下载:
音乐播放器-3首lcd1602显示歌词.zip (507.25 KB, 下载次数: 74)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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