OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 41200|回复: 17

易上手的蜂鸣器放歌

[复制链接]

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
发表于 2013-2-8 17:32:49 | 显示全部楼层 |阅读模式

    
简明易懂易上手!
单片机产生音乐的原理:
     音乐的产生主要是通过单片机的
I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半周期的时间,每当计时到后就输出脉冲的I/O口反相,这样就在此I/O口上得到此脉冲的频率。

        通常,利用单片机的内部定时器0,工作在方式一下,改变计数初始值TH0TL0来产生不同的率。

        例如,若单片机采用12MHzs晶振,要产生频率为587Hzs的音频脉冲时,其音频信号的脉冲周期T=1/587=1703.5775us,半周期时间为852us,因此总要令计时器计数=852us/1us=852,在每计数852时将I/O口反相,就得到C大调的中调Re

        由于定时器0的在方式一计数方式为16位计数器,最多只能装载的数为216次方即65536个,也就是说定时器计数到65536就会进入中断函数,而在中断函数中将输出脉冲的I/O口反相即可,故只需设置好定时器0的初值就可以了发出特定的音频了。初值与音频的对应关系见下表所示:

音频

定时器初值

1do

63628

2re

63835

3mi

64021

4fa

64103

5so

64260

6la

64400

7si

64524

1do

64580

2re

64684

3mi

64777

4fa

64820

5so

64898

6la

64968

7si

65030

1do

65058

2re

65110

3mi

65157

4fa

65160

5so

65217

6la

65252

7si

65282


#include"STC12C5A.h"
int tab[]={64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178,65217,65252,65282}; //网上找到的音符与定时器初值对照表中的数据,用来设定时器0初值
sbit bell=P1^3;//位定义蜂鸣器  
int i; //用于赋定时器0初值
/*延时函数*/
void delay_ms(unsigned int time)
{
 unsigned int t;
 for(;time>0;time--)
 {
  t=1500;
  while(t--);
 }
}
/*定时器0初始化函数*/
void Timer0_init()
{
  TMOD=0x01;//选择定时器0方式1
 ET0=1;   //开启定时器0中断
 EA=1;  
 TR0=1;
 TL0=tab;
 TH0=tab>>8;
}
void Timer0_Isp() interrupt 1
{
  TL0=tab;
 TH0=tab>>8;
 bell=!bell;
}
//放音符的数组前面记得加个code,延迟时间凭乐感吧!要关掉蜂鸣器貌似蜂鸣器跟定时器都要关哦,歌曲暂停与播放,强烈推荐用外部中断!

void main()
{
 int s;
code int song[]={6,5,6,8,9,10,7,6,5,3,5,9,8};
code int song1[]={2,3,5,6,5,3,2,1} ;
code song2[]={10,9,8,5,9,3,5,9,5};
code int song3[]={8,9,10,12,13,10,9};
code int song4[]={9,8,9,10,12,10};

 /*心中有江山的人岂能快意潇洒*/
 for(s=0;s<13;s++)
 {
   i=song-1;
  Timer0_init();
  Timer0_init();
  delay_ms(450);

 }
 delay_ms(500);
 /*我只求于你共华发*/
 for(s=0;s<8;s++)
 {
   i=song1-1;
  Timer0_init();
  Timer0_init();
  delay_ms(450);

 }
 delay_ms(700);
 /*剑出鞘,恩怨了*/
 for(s=1;s<3;s++)
 { 
     i=4;
  Timer0_init();
  Timer0_init();
  delay_ms(450);
  i=5;
  Timer0_init();
  Timer0_init();
  delay_ms(450);
  i=9;
  Timer0_init();
  Timer0_init();
  delay_ms(700);
 }
/*谁笑*/
  i=7;
  Timer0_init();
  Timer0_init();
  delay_ms(450);
  i=8;
  Timer0_init();
  Timer0_init();
  delay_ms(1000);
/*我只求今朝拥你入环抱*/
 for(s=0;s<9;s++)
 {
   i=song2-1;
  Timer0_init();
  Timer0_init();
  delay_ms(450);

 }
 delay_ms(100);
 i=7;
 Timer0_init();
 Timer0_init();
 delay_ms(1000); 
 /*红尘客栈风似刀*/
 for(s=0;s<7;s++)
 {
   i=song3-1;
  Timer0_init();
  Timer0_init();
  delay_ms(450);

 }
 delay_ms(1000);
 /*骤雨落宿命敲*/
 for(s=0;s<6;s++)
 {
   i=song4-1;
  Timer0_init();
  Timer0_init();
  delay_ms(450);

 }
 delay_ms(1000);
}

当我的世界不一样,那就让我不一样
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1863
金钱
1863
注册时间
2011-3-29
在线时间
139 小时
发表于 2013-2-9 10:18:31 | 显示全部楼层
五天就能写这些,叫我这玩了五年也不会的人情何以堪。
业余程序玩家。
回复 支持 1 反对 0

使用道具 举报

4

主题

40

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
221
金钱
221
注册时间
2013-1-29
在线时间
29 小时
发表于 2013-2-13 10:53:06 | 显示全部楼层
原始的方法,有时更有效果
什么是母体?什么是真实?——《黑客帝国》 我在电子世界里?——《创战纪》 ...这里是世界尽头...——《异次元骇客》
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2013-2-15 19:46:55 | 显示全部楼层
帮顶
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2013-4-22 16:00:36 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
 楼主| 发表于 2013-4-22 16:30:12 | 显示全部楼层
回复【5楼】xouou_53320:
---------------------------------
嗯。。。确实哦,当初我只是想看看别人能不能吐一下槽,然后提一些修改意见的其实
当我的世界不一样,那就让我不一样
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2013-4-22 16:46:37 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
 楼主| 发表于 2013-4-23 01:05:45 | 显示全部楼层
回复【7楼】xouou_53320:
---------------------------------
这样行了吧。。。。
当我的世界不一样,那就让我不一样
回复 支持 反对

使用道具 举报

6

主题

153

帖子

0

精华

初级会员

Rank: 2

积分
197
金钱
197
注册时间
2013-4-4
在线时间
0 小时
发表于 2013-4-24 23:21:05 | 显示全部楼层
回复【8楼】越不出雷池:
---------------------------------
程序是简单嘛 但是可以拓展呀
比如几首歌可以切换
或者可以更改播放的速度
或者做个LCD的显示
~~~~ 欢迎讨论,拒绝谩骂 ~~~~
回复 支持 反对

使用道具 举报

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
 楼主| 发表于 2013-4-25 00:13:21 | 显示全部楼层
回复【9楼】兰斯洛:
---------------------------------
额。。。好久没碰过蜂鸣器放歌,以后有时间在搞吧。。。谢谢您提出的宝贵意见!
当我的世界不一样,那就让我不一样
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2013-4-27
在线时间
0 小时
发表于 2013-4-30 23:27:48 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2012-9-14
在线时间
2 小时
发表于 2013-5-11 23:11:53 | 显示全部楼层
大神。
回复 支持 反对

使用道具 举报

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
 楼主| 发表于 2013-5-12 00:09:03 | 显示全部楼层
改了帖子,这次总能沉下去吧。。。
当我的世界不一样,那就让我不一样
回复 支持 反对

使用道具 举报

4

主题

55

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2013-3-8
在线时间
5 小时
发表于 2013-5-17 19:32:23 | 显示全部楼层
嗯,不错,我也来玩下
我的未来不是梦!
回复 支持 反对

使用道具 举报

4

主题

55

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2013-3-8
在线时间
5 小时
发表于 2013-5-18 20:16:33 | 显示全部楼层
我自己改了一下

#include"reg52.h"
int tab[]={64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178,65217,65252,65282}; 
//网上找到的音符与定时器初值对照表中的数据,用来设定时器0初值
sbit bell=P1^3;//位定义蜂鸣器  
int i=0; //用于赋定时器0初值
/*延时函数*/
void delay_ms(unsigned int time)
{
 unsigned int j;
 for(;time>0;time--)
 for(j=122;j>0;j--);
}
/*定时器0初始化函数*/
void Timer0_init()
{
  TMOD=0x01;//选择定时器0方式1
 ET0=1;   //开启定时器0中断
 EA=1;   
 TR0=1;
 TL0=tab;
 TH0=tab>>8;
}
void Timer0_Isp() interrupt 1
{
  TL0=tab;
 TH0=tab>>8;
 bell=!bell;
}
//放音符的数组前面记得加个code,延迟时间凭乐感吧!要关掉蜂鸣器貌似蜂鸣器跟定时器都要关哦,歌曲暂停与播放,强烈推荐用外部中断!

void main()
{
int s=0,len;
//《愿得一人心》的前一部分 网上搜的乐谱,然后填的数据
code char song[]={0,1,1,2,3,3,3,3,3,2,3,5,5,5,2,0,
5,6,7,7,8,8,8,8,3,3,8,7,6,5,0,
5,5,6,8,8,0,
1,1,6,5,6,3,0,
1,2,3,4,4,4,3,4,8,7,8,7,6,5,0,
1,1,2,3,3,3,3,3,2,3,5,6,5,2,0,
5,6,7,8,8,8,8,8,3,3,8,7,6,5,0,
1,1,6,5,6,3,0,
1,2,3,4,4,4,3,4,8,7,8,7,6,5,0,
0,5,5,11,10,9,10,0,//只愿得一人心
10,9,10,12,12,0,
12,12,11,10,9,8,0,
8,8,8,7,8,9,10,0
};
len=sizeof(song);//测量数组字节数,这样就不用数有多少数了  
while(1)
{
if(song)
{
i=song-1;
Timer0_init();
Timer0_init();
delay_ms(400);
TR0=0;
delay_ms(50);//使字与字之间产生间隔
TR0=1;
}else
{
TR0=0;
delay_ms(450);
TR0=1;
}
s++;
if(s>=len)
s=0;
}
}
蜂鸣器一端接5V,一端接I/O口就能响,实物响声不大,仿真响声还可以

proteus仿真测试图



我的未来不是梦!
回复 支持 反对

使用道具 举报

8

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
82
金钱
82
注册时间
2013-1-29
在线时间
0 小时
 楼主| 发表于 2013-5-20 20:33:41 | 显示全部楼层
回复【15楼】happy郭惊鸿:
---------------------------------
好厉害哦~~~~不错啦
当我的世界不一样,那就让我不一样
回复 支持 反对

使用道具 举报

8

主题

130

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2013-4-24
在线时间
0 小时
发表于 2013-5-21 18:30:40 | 显示全部楼层
牛逼     我觉得那个没啥意思   也没深入搞过
你猜你猜你再猜
回复 支持 反对

使用道具 举报

2

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2015-11-3
在线时间
9 小时
发表于 2015-11-12 16:39:46 | 显示全部楼层
回复【6楼】越不出雷池:
---------------------------------
求助 我看了好久有些地方看不懂  能帮忙解释下吗?
Timer0_init();
Timer0_init();这里为什么初始化2次
i=song-1;这里为什么要减一。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 12:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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