蜂鸣器相关文章索引

蜂鸣器相关文章索引

  1. 蜂鸣器:基础(1)
  2. 蜂鸣器(2):12V有源蜂鸣器
  3. 蜂鸣器(3):ezBuzzer库

如何利用蜂鸣器制作MIDI音乐

引言:在单片机开发中我们经常会用到蜂鸣器实现一些简单提示的功能,但如何利用单片机制作一些更有趣的事情呢,今天我们将利用蜂鸣器来制作一首好听的MIDI音乐。很多人可能会觉得没必要,用手机我们就就可以想听什么歌就听什么歌了,但其实对于我们单片机开发者来说自己动手写一个程序蜂鸣器按照我们给的频率响起来,会让我们的开发过程变的更加有趣,也使得我们拥有更加浓厚的兴趣学下去。

一蜂鸣器简介
有源蜂鸣器和无源蜂鸣器的区别:
在这里插入图片描述
这里我们使用的是无源蜂鸣器,通过单片机予相应的频率使它发出相应的声音。

要使无源蜂鸣器鸣响需要端口不断输出高低变化的脉冲信号,当信号频率不同时发出的声音就不同,根据这个原理,只要我们根据音乐乐谱让端口连续输出不同频率的信号蜂鸣器的鸣响就可以组成一支音乐啦。

在这里插入图片描述
如图单片机输出的信号是这样的一个高低电平信号,频率周期的数量就是蜂鸣器鸣响的时长,而改变每个频率周期中高低电平的比例就可以改变无源蜂鸣器发出的声音。
在这里插入图片描述
根据C字符对照表我们可以得到每个音调对应的频率。
二、《小星星》MIDI音乐制作过程

在这里插入图片描述

这是《小星星》的乐谱信息,根据上面的音调频率对照表,我们就可以把乐谱信息转化为频率信息。
相关乐谱信息:
乐谱图中重点看每个拍的时间信息
J=100表示每分钟有100拍,即60s=100拍,所以一拍的时间约为600ms
根据他是多少拍就可以算出蜂鸣器一个音调鸣响的时间
在这里插入图片描述

在我们的程序中我们把音乐的每个音调的频率信息和发声时间长度为一组放入 music1[ ]数组中其中奇数为音调频率信息偶数为发声时间长度,其中每个音调的发声时间长度可以根据乐谱看他是多少拍,根据一拍为多长时间可以计算出每个音调的时间。如在这首歌中每个音调都是一拍而这里一拍为600ms所以这里我们
每个音调发声时间都为600ms,关于乐谱的更多信息可以到网上查找。

uc16 music1[64] = {  //音乐1的数据表(奇数是对应音调频率,偶数是发声时间长度
  523, 600,
  523, 600,
  784, 600,
  784, 600,
  880, 600,
  880, 600,
  784, 600,
  0, 1200,
  698, 600,
  698, 600,
  659, 600,
  659, 600,
  587, 600,
  587, 600,
  523, 600,
  0, 1200,
  784, 600,
  784, 600,
  698, 600,
  698, 600,
  659, 600,
  659, 600,
  587, 600,
  0, 1200,
  784, 600,
  784, 600,
  698, 600,
  698, 600,
  659, 600,
  659, 600,
  587, 600,
  0, 1200
};

void MIDI_PLAY(void) {  //MIDI音乐
  u16 i, e;
  for (i = 0; i < 32; i++) {  //这里因为这首歌有32个音调所以这里循环32次
    for (e = 0; e < music1[i * 2] * music1[i * 2 + 1] / 1000; e++) {
      GPIO_WriteBit(BUZZERPORT, BUZZER, (BitAction)(0));   //蜂鸣器接口输出0
      delay_us(500000 / music1[i * 2]);                    //延时
      GPIO_WriteBit(BUZZERP ORT, BUZZER, (BitAction)(1));  //蜂鸣器接口输出高电平1
      delay_us(500000 / music1[i * 2]);                    //延时
    }
  }
}

0. 在Arduino IDE中写个Arduino程序控制无源型蜂鸣器模块

int pinBuzzer = 3; //管脚D3连接到蜂鸣器模块的信号脚
 
void setup() {
  pinMode(pinBuzzer, OUTPUT); //设置pinBuzzer脚为输出状态
}
 
void loop() { 
   long frequency = 300; //频率, 单位Hz
 
   //用tone()函数发出频率为frequency的波形
   tone(pinBuzzer, frequency );
   delay(1000); //等待1000毫秒
   
   noTone(pinBuzzer);//停止发声
   delay(2000); //等待2000毫秒
}

1. 生日快乐

#define Do 262  
#define Re 294  
#define Mi 330  
#define Fa 349  
#define Sol 392  
#define La 440  
#define Si 494  
#define Do_h 523  
#define Re_h 587  
#define Mi_h 659  
#define Fa_h 698  
#define Sol_h 784  
#define La_h 880  
#define Si_h 988
int length;
int scale[]={Sol,Sol,La,Sol,Do_h,Si,
             Sol,Sol,La,Sol,Re_h,Do_h,
             Sol,Sol,Sol_h,Mi_h,Do_h,Si,La,
             Fa_h,Fa_h,Mi_h,Do_h,Re_h,Do_h};        //生日歌曲谱
float durt[]=
{
  0.5,0.5,1,1,1,1+1,
  0.5,0.5,1,1,1,1+1,
   0.5,0.5,1,1,1,1,1,
    0.5,0.5,1,1,1,1+1,
};                                                        //音长
int tonepin=7;   //用8号引脚
int ledpin = 13;
void setup()
{
  pinMode(tonepin,OUTPUT);
  pinMode(ledpin,OUTPUT);
  length=sizeof(scale)/sizeof(scale[0]);   //计算长度
}
void loop()
{
  for(int x=0;x<length;x++)
  {
    tone(tonepin,scale[x]);
    digitalWrite(ledpin,HIGH);
    delay(500*durt[x]);   //这里用来根据节拍调节延时,500这个指数可以自己调整
    digitalWrite(ledpin,LOW);
    delay(100*durt[x]);
    noTone(tonepin);
  }
  delay(3000);
}

2. 天空之城

/*************以下变量无需修改**********************/
int note[21][7] = {                /*标准频率对照表*/
  /*A-G大调降音*/
  {221, 248, 278, 294, 330, 371, 416},       //A大调
  {248, 278, 294, 330, 371, 416, 467},       //B大调
  {131, 147, 165, 175, 196, 221, 248},       //C大调
  {147, 165, 175, 196, 221, 248, 278},       //D大调
  {165, 175, 196, 221, 248, 278, 294},       //E大调
  {175, 196, 221, 248, 278, 294, 330},       //F大调
  {196, 221, 248, 278, 294, 330, 371},       //G大调
  /*A-G大调标准音*/
  {441, 495, 556, 624, 661, 742, 833},
  {495, 556, 624, 661, 742, 833, 935},
  {262, 294, 330, 350, 393, 441, 495},
  {294, 330, 350, 393, 441, 495, 556},
  {330, 350, 393, 441, 495, 556, 624},
  {350, 393, 441, 495, 556, 624, 661},
  {393, 441, 495, 556, 624, 661, 742},
  /*A-G大调升音*/
  {882, 990, 1112, 1178, 1322, 1484, 1665},
  {990, 1112, 1178, 1322, 1484, 1665, 1859},
  {525, 589, 661, 700, 786, 882, 990},
  {589, 661, 700, 786, 882, 990, 1112},
  {661, 700, 786, 882, 990, 1112, 1178},
  {700, 786, 882, 990, 1112, 1178, 1322},
  {786, 882, 990, 1112, 1178, 1322, 1484},

};

/*************以下变量依据实际修改****************/
int buzzerPin = 7;              /*蜂鸣器引脚位置*/
int BPM = 400;                  /*一拍的时间*/
int Scale = 4;                  /*设置大调,A-Z分别对应1-7*/
float rate = 0.1;               /*发声时间占一拍时间的比率*/

/*****TMD 蜂鸣器唱歌真难听*****/
//天空之城
int pitch[] =
{
  6, 7, 1, 7, 1, 3, 7, 3, 6, 5, 6, 1, 5, 3, 4, 3, 4, 1, 3, 1, 7, 4, 4, 7, 7, 6, 7, 1, 7, 1, 3, 7, 3, 3, 6, 5, 6, 1, 5, 3, 4, 1, 7, 1, 2, 3, 1, 1, 1, 7, 6, 7, 5, 6, 6, 6, 1, 2, 3, 2, 3, 5, 2, 2, 2, 5, 1, 7, 1, 2, 3, 3, 3, 3, 3, 6, 7, 1, 7, 1, 2, 1, 5, 5, 5, 4, 3, 2, 1, 3, 3, 3, 3, 6, 6, 5, 5, 3, 2, 1, 1, 1, 2, 1, 2, 5, 3, 3, 3, 3, 6, 6, 5, 5, 3, 2, 1, 1, 1, 2, 1, 2, 7, 6, 6, 6, 0,
};
int rise[] =
{
  0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
};
float mlength[] =
{
  0.500, 0.500, 1.500, 0.500, 1.000, 1.000, 3.000, 1.000, 0.500, 1.000, 1.000, 1.000, 3.000, 1.000, 1.500, 0.500, 0.500, 1.500, 3.000, 1.000, 1.500, 0.500, 0.500, 1.000, 3.000, 0.500, 0.500, 1.500, 0.500, 1.000, 1.000, 3.000, 0.500, 0.500, 1.500, 0.500, 1.000, 1.000, 3.000, 1.000, 1.000, 0.500, 1.500, 1.000, 1.000, 0.500, 0.500, 2.000, 0.500, 0.500, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 0.500, 0.500, 1.500, 0.500, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.500, 0.500, 1.000, 0.500, 0.500, 1.000, 1.000, 1.000, 1.000, 0.500, 0.500, 1.000, 0.500, 0.500, 1.000, 1.500, 0.500, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.500, 0.500, 1.500, 0.500, 0.500, 0.500, 1.000, 1.000, 1.000, 1.500, 0.500, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.500, 0.500, 1.500, 0.500, 0.500, 0.500, 1.000, 1.000, 1.000, 1.500, 0.500, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000,
};
/*两只老虎
  int pitch[] =
  {
  1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5, 5, 6, 5, 4, 3, 1, 0, 0, 1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5,
  };
  int rise[] =
  {
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  };
  float mlength[] =
  {
  1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 2.000, 1.000, 1.000, 2.000, 0.500, 0.500, 0.500, 0.500, 1.000, 1.000, 1.000, 3.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 2.000, 1.000, 1.000, 2.000,
  };*/
/*追光者*/
/*int pitch[] =
  {
  0, 0, 0, 0, 6, 7, 1, 7, 3, 3, 5, 5, 1, 2, 1, 2, 2, 5, 3, 6, 7, 1, 7, 3, 3, 5, 1, 5, 1, 2, 3, 1, 7, 6, 7, 1, 1, 3, 2, 7, 6, 5, 6, 7, 7, 2, 1, 0, 1, 7, 1, 0, 6, 6, 7, 1, 7, 6, 5, 0, 1, 2,
  };

  int rise[] =
  {
  1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2,
  };



float mlength[] ={
  1.000, 1.000, 1.000, 0.500, 0.250, 0.250, 0.500, 0.250, 0.250, 0.500, 0.500, 1.000, 1.000, 0.500, 0.250, 0.250, 0.500, 0.500, 1.000, 0.500, 0.500, 0.500, 0.250, 0.250, 0.500, 0.500, 1.000, 3.000, 0.500, 0.500, 1.000, 0.500, 0.500, 0.500, 0.250, 0.250, 0.500, 0.500, 1.000, 0.500, 0.500, 0.500, 0.250, 0.250, 0.500, 0.500, 1.000, 0.500, 0.250, 0.250, 1.000, 0.250, 0.250, 0.250, 0.250, 0.500, 0.500, 0.500, 0.500, 1.000, 0.500, 0.500,
};*/

void setup() {
  pinMode(buzzerPin, OUTPUT);

}

void loop() {
  int i;
  int Frequency;
  int toneTime, notoneTime;

  for (i = 0; i < sizeof(note) / sizeof(int); i++)
  {
    if (pitch[i] != 0)
    {
      Frequency = note[Scale + rise[i] * 7 ][pitch[i]];

      toneTime = mlength[i] * BPM * rate;
      notoneTime = mlength[i] * BPM - toneTime;

      tone(buzzerPin, Frequency);
      delay(toneTime);
      
      noTone(buzzerPin);
      delay(notoneTime);
    }

    else delay(BPM * mlength[i]);
  }

  delay(10000);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔚蓝慕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值