51单片机入门_江协科技_25~26_OB记录的笔记_蜂鸣器教程

25. 蜂鸣器

  • 25.1. 蜂鸣器介绍

    •蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号

    •蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器(开发板上用的无源蜂鸣器)

    •有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定

    •无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

  • 25.2. 驱动电路

    • 三极管驱动

    • 集成电路驱动,开发板ULN2003D,Proteus有器件,开发板BZ接P2^5引脚。

  • 25.3. ULN2003

  • 25.4. 键盘与音符对照

    • 图片中所示为钢琴键盘一部分
    • 中央c1~b1为一组(低1音阶),7个白键,5个黑键,此图显示4组,c2~b2为一组(低2音阶),c~b为一组(正常音阶),C~B为一组(高一音阶)
    • c1右侧黑键为c1#,高半,也可表示为b d1,低半
  • 25.5. 简谱-小星星,简单识谱

    • 左上角1=C4/4,表示C调,每节4拍,每1/4拍为一个音符;
    • 6 6 5 -,5右侧-表示5音占2个1/4拍,以下同理;
  • 25.6. 简谱-天空之城

    • 左上角1=D4/4表示D调,每节4拍,每1/4拍为一个音符;
    • 假定一拍500ms,6 7带下划线代表6 7为一拍,一个音符就是250mm;
    • 1上有一点表示高音阶,右侧有一点表示1.5拍为750ms;
    • 77带上圆括号的表示这2个音符连音,即250ms+250ms=500ms;
  • 25.7. 音符与频率对照

    PPT中的图片整理为如下表格:

音符 频率计算 频率/2 频率/2的取整 备注
低音1 261.6255653 130.8127827 131
低音1# 277.182631 138.5913155 139
低音2 293.6647679 146.832384 147
低音2# 311.1269837 155.5634919 156
低音3 329.6275569 164.8137785 165
低音4 349.2282314 174.6141157 175
低音4# 369.9944227 184.9972114 185
低音5 391.995436 195.997718 196 440/2^(2/12)
低音5# 415.3046976 207.6523488 208 440/2^(1/12)
低音6 440 220 220 基准频率
低音6# 466.1637615 233.0818808 233 440*2^(1/12)
低音7 493.8833013 246.9416506 247 440*2^(2/12)
中音1 523.2511306 261.6255653 262
中音1# 554.365262 277.182631 277
中音2 587.3295358 293.6647679 294
中音2# 622.2539674 311.1269837 311
中音3 659.2551138 329.6275569 330
中音4 698.4564629 349.2282314 349
中音4# 739.9888454 369.9944227 370
中音5 783.990872 391.995436 392
中音5# 830.6093952 415.3046976 415
中音6 880 440 440
中音6# 932.327523 466.1637615 466
中音7 987.7666025 493.8833013 494
高音1 1046.502261 523.2511306 523
高音1# 1108.730524 554.365262 554
高音2 1174.659072 587.3295358 587
高音2# 1244.507935 622.2539674 622
高音3 1318.510228 659.2551138 659
高音4 1396.912926 698.4564629 698
高音4# 1479.977691 739.9888454 740
高音5 1567.981744 783.990872 784
高音5# 1661.21879 830.6093952 831
高音6 1760 880 880
高音6# 1864.655046 932.327523 932
高音7 1975.533205 987.7666025 988

26. 蜂鸣器播放提示音&音乐

  • 26.1. 第一个测试程序功能是实现4个独立按键在按下并松开后,8位数码管显示相应的按键的数值1~4,没有按下的时候显示0,需要用到之前的模块程序Four_Key(针对独立按键操作)以及nixietube(针对8位数码管显示)

  • 26.2. 程序定义蜂鸣器的引脚P2^5,貌似按照开发板原理图P1^5不正确,实物开发板蜂鸣器不响,因为蜂鸣器有声音需要500Hz左右的频率,周期2ms,因此定义Buzzer每隔1ms切换一次高低电平并持续1ms即可模拟周期2ms(500Hz)的蜂鸣器声音频率;

  • 26.3. Proteus中暂时还么有找到仿真无源蜂鸣器的方法,暂时只能放上程序,用实物开发板进行测试;

    #include <REGX52.h>
    #include "delay_xms.h"
    #include "Four_Key.h"
    #include "nixietube.h"

    sbit Buzzer=P2^5;
    unsigned char KeyNum;
    unsigned int i;

    void main()
    {
    NixieTube(1,0);
    while(1)
    {
    KeyNum=Four_Key();
    if(KeyNum)
    {
    for(i=0;i<500;i++)
    {
    Buzzer=!Buzzer;
    delay_xms(1);
    }
    NixieTube(1,KeyNum);
    }
    }

    }

nixietube数码管显示程序的后2句需要注释掉,因为目前测试程序数码管为静态显示,无需刷新;

#include <REGX52.H>			//因为该程序调用<REGX52.H>所以要添加
#include "delay_xms.h"		//因为该程序调用<delay_xms.h>所以要添加

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

void NixieTube(unsigned char Location,Number)
{
	switch(Location)
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];//数码管消影,因为位选-段选-位选-段选,段选数据与位选穿位导致
	//delay_xms(1); //数码管稳定显示1ms;蜂鸣器提示音实验无需延时
	//P0=0x00;//清零;蜂鸣器提示音实验无需清零,静态显示
}
  • 26.4. 在上述程序基础上对程序进行模块化处理,生成一个Buzzer.c与Buzzer.h的模块化程序;

    #include <REGX52.H>
    #include <INTRINS.H>

    sbit Buzzer=P2^5; //蜂鸣器端口
    /**
    * @brief 蜂鸣器延时函数,延时500us
    * @param 无
    * @retval 无
    */

    void Buzzer_Delay500us(void) //@12.000MHz
    {
    unsigned char data i;

      _nop_();
      i = 247;
      while (--i);
    

    }

    /**
    * @brief 蜂鸣器鸣响函数
    * @param ms发声的时长毫秒
    * @retval 无
    */

    void Buzzer_Time(unsigned int ms)
    {

      unsigned int i;
      for(i=0;i<ms*2;i++)
      {
      	Buzzer=!Buzzer;
      	Buzzer_Delay500us();
      }
    

    }

Buzzer.h的文件如下

#ifndef _BUZZER_H_  
#define _BUZZER_H_  

void Buzzer_Time(unsigned int ms); //调用函数使蜂鸣器响ms毫秒

#endif

main.c程序修改如下:

#include <REGX52.h>
#include "Four_Key.h"
#include "nixietube.h"
#include "Buzzer.h"

unsigned char KeyNum;

void main()
{
	NixieTube(1,0);
	while(1)
	{
		KeyNum=Four_Key();
		if(KeyNum)
			{
				Buzzer_Time(100);
				NixieTube(1,KeyNum);
			}
	}
	
}
  • 26.5. 因为不同的声音频率对应不同的音符,以440Hz基础频率举例,对应的频率周期为2272us,如采用中断溢出切换Buzzer的高低电平输出声音频率,需要以1/2频率周期进行高低电位翻转,中断溢出值65536-1/2周期1136计算出中断溢出值64400
音符 频率Hz 频率取整 周期us 1/2周期us 1/2周期取整 中断溢出值 中断溢出计算
1 261.6255653 262 3816.793893 1908.396947 1908 65536 63628
1# 277.182631 277 3610.108303 1805.054152 1805 65536 63731
2 293.6647679 294 3401.360544 1700.680272 1701 65536 63835
2# 311.1269837 311 3215.434084 1607.717042 1608 65536 63928
3 329.6275569 330 3030.30303 1515.151515 1515 65536 64021
4 349.2282314 349 2865.329513 1432.664756 1433 65536 64103
4# 369.9944227 370 2702.702703 1351.351351 1351 65536 64185
5 391.995436 392 2551.020408 1275.510204 1276 65536 64260
5# 415.3046976 415 2409.638554 1204.819277 1205 65536 64331
6 440 440 2272.727273 1136.363636 1136 65536 64400
6# 466.1637615 466 2145.922747 1072.961373 1073 65536 64463
7 493.8833013 494 2024.291498 1012.145749 1012 65536 64524
1 523.2511306 523 1912.045889 956.0229446 956 65536 64580
1# 554.365262 554 1805.054152 902.5270758 903 65536 64633
2 587.3295358 587 1703.577513 851.7887564 852 65536 64684
2# 622.2539674 622 1607.717042 803.8585209 804 65536 64732
3 659.2551138 659 1517.450683 758.7253414 759 65536 64777
4 698.4564629 698 1432.664756 716.3323782 716 65536 64820
4# 739.9888454 740 1351.351351 675.6756757 676 65536 64860
5 783.990872 784 1275.510204 637.755102 638 65536 64898
5# 830.6093952 831 1203.369434 601.6847172 602 65536 64934
6 880 880 1136.363636 568.1818182 568 65536 64968
6# 932.327523 932 1072.961373 536.4806867 536 65536 65000
7 987.7666025 988 1012.145749 506.0728745 506 65536 65030
1 1046.502261 1047 955.1098376 477.5549188 478 65536 65058
1# 1108.730524 1109 901.7132552 450.8566276 451 65536 65085
2 1174.659072 1175 851.0638298 425.5319149 426 65536 65110
2# 1244.507935 1245 803.2128514 401.6064257 402 65536 65134
3 1318.510228 1319 758.1501137 379.0750569 379 65536 65157
4 1396.912926 1397 715.8196135 357.9098067 358 65536 65178
4# 1479.977691 1480 675.6756757 337.8378378 338 65536 65198
5 1567.981744 1568 637.755102 318.877551 319 65536 65217
5# 1661.21879 1661 602.0469597 301.0234798 301 65536 65235
6 1760 1760 568.1818182 284.0909091 284 65536 65252
6# 1864.655046 1865 536.1930295 268.0965147 268 65536 65268
7 1975.533205 1976 506.0728745 253.0364372 253 65536 65283
  • 26.6. 中断定时器模块程序里面的如下两句只是设置定时器的第一次初始化的初始值,后续不调用

      TL0 = 0x18;				//设置定时初始值
      TH0 = 0xFC;				//设置定时初始值
    
  • 26.7. 测试将音符做成数组并测试

    #include <REGX52.h>
    #include "delay_xms.h"
    #include "TimeR0.h"

    sbit Buzzer=P2^5;
    unsigned int FreqTable[]={
    63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
    64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
    65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
    };

    void main()
    {
    TimeR0_Init();
    while(1)
    {

      }
    

    }

    void TimeR0_Routine() interrupt 1 //中断子函数
    {
    TL0=FreqTable[0]%256; //设置定时初始值
    TH0=FreqTable[0]/256; //设置定时初始值
    Buzzer=!Buzzer;
    }

  • 26.8. 在上述程序基础上,结合简谱的小星星,SPEED定义500为正常速度,250速度加快;

    #include <REGX52.h>
    #include "delay_xms.h"
    #include "TimeR0.h"

    sbit Buzzer=P2^5;

    #define SPEED 250 //定义speed便于调速

    unsigned int FreqTable[]={
    0,
    63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
    64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
    65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
    };//定义0位数据为休止符

    unsigned char Music[]={
    13,4,
    13,4,
    20,4,
    20,4,
    22,4,
    22,4,
    20,8,
    0,4, //0为休止符
    18,4,
    18,4,
    17,4,
    17,4,
    15,4,
    15,4,
    13,8,
    0xff, //终止判断
    }; //定义1/16音符时长为基准时长定义为1,后续以此为基准

    unsigned char FreqSelect,MusicSelect;
    void main()
    {
    TimeR0_Init();
    while(1)
    {
    if(Music[MusicSelect]!=0xff)
    {
    FreqSelect=Music[MusicSelect];
    MusicSelect++;
    delay_xms(SPEED/4*Music[MusicSelect]);
    MusicSelect++;
    TR0=0;
    delay_xms(5);
    TR0=1;
    }
    else
    {
    MusicSelect=0;
    }
    }

    }

    void TimeR0_Routine() interrupt 1 //中断子函数
    {
    if(FreqTable[FreqSelect])
    {
    TL0=FreqTable[FreqSelect]%256; //设置定时初始值
    TH0=FreqTable[FreqSelect]/256; //设置定时初始值
    Buzzer=!Buzzer;
    }
    }

相关推荐
GeekAlice3 分钟前
算法笔记/USACO Guide GOLD金组Graphs并查集Disjoint Set Union
c++·经验分享·笔记·学习·算法
写代码的橘子n13 分钟前
软件工程笔记二—— 软件生存期模型
笔记·语言模型·软件工程
A_cot2 小时前
一篇Spring Boot 笔记
java·spring boot·笔记·后端·mysql·spring·maven
2401_858286119 小时前
L7.【LeetCode笔记】相交链表
笔记·leetcode·链表
龙中舞王10 小时前
Unity学习笔记(2):场景绘制
笔记·学习·unity
mirrornan11 小时前
产品如何3D建模?如何根据使用场景选购3D扫描仪?
科技·3d·3d建模·3d模型·三维扫描
青椒大仙KI1111 小时前
24/11/7 算法笔记 PCA主成分分析
笔记·算法·信息可视化
光明中黑暗12 小时前
机器学习 笔记
人工智能·笔记·机器学习
明辉光焱13 小时前
Node.js笔记
javascript·笔记·node.js
RationalDysaniaer13 小时前
gin入门
笔记·gin