大家好,欢迎来到IT知识分享网。
一、蜂鸣器介绍
- 蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号
- 蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器
- 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
- 无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
二、驱动电路
- 三极管驱动
如果电路处于放大状态(放大电路),那么就可以通过基极(连接电阻的那一端)来控制导通和截止关系。三级管有NPN形和PNP形:
- 放大状态:放大状态是指放大器工作时的状态,即输入信号经过放大器放大后的输出信号状态。放大器的作用是将输入信号放大到一定的幅度,从而使得信号能够被后续电路或设备正确地处理和识别
- NPN:给1导通,给0截断
- PNP:给0导通,给1截断
- 集成电路驱动
三、ULN2003
因为芯片中都是非门,所以给1,是低电平,给1时导通,给0时类似于处于高阻状态,既不是高电平,也不是低电平。
四、键盘与音符对照
简单的学习一下乐理知识:
- 钢琴键盘是可分组的,中央C~b1,称为小字1组,一组由7个白键5个黑键组成的,左边的为小字组,小字组左边为大字组,如果大字左边还有则称为大字1组,小字1组右边为小字2组,以此类推。
- 每个组相同的音都相差8度,比如c1到从c2要升高8度,c1到c要降低8度。
- 相邻的两个音是半音的关系,相邻不是单看白键,是黑白同看,例如c1和d1中间的黑键和c1差半音,和d1也差半音,c1和b1差一个全音,e1和f1是相邻的白键,他们也是差半音。
- 根据上图所示,音名c1对应着简谱中的1,c2对应着简谱中的1‘(1上一点)代表升高8度,c对应着(1下一点)下降8度,C对应着(1下两点)代表下降两个8度,这是白键的表示方式。如果是黑键则需要用到#(升音符号)、b(降音符号)。例如向弹c1和b1之间的黑键符号表示为^#1或者^b2(#和b在左上方)表示含义为升半音,如果是弹f1也可以用^#3,表示e1升半音弹f1键。
五、音符与频率对照
- 频率由低音6为基准,对应着a,频率为440,从这个基准开始到a1(中音6)时频率为880,在A时为220,中间总共有12个键(包括黑键),中间以等比数列进行平分的,所以又称为12平分率
所以从a到b的频率为440*2^(1/12) = 466.1638,从a到g则是440/2^(1/12) = 415.3047。
- 在单片机中我们用定时器中断来产生频率,定时器中断的时间是TH0和TL0的重装值确定的,接下来需要确定一下重装值,单片机不好直接产生频率,所以要先计算各个频率的周期值,周期值等于1/频率单位是s,我们将单位换成us。
- 51单片机是12T单片机,他的机器周期是震荡周期的十二分之一,假如晶振是12MHZ的,那么机器周期就是1MHZ,一个周期定时器计数加一,定时器加1的时间就是1us(如果是11.0592MHZ则为机器周期 = 11.0595/12,定时器加1的时间则是1.机器周期)。
- I/O口翻转2次才是一个周期,先置1,再置0,如果一个周期是3000多us那么翻转的频率是周期的2倍,翻转的时间是他的二分之一,所以重装载时间 = 65536 – 周期/2。
六、简谱
二分音符 四分音符 全音音符 八分音符
- 一般以4分音符为精准,比如4分音符是500ms,那么二分音符就是1s,全音音符就是2s。
- 在小星星简谱中,可以看到没有升降音(由于是C调,全弹白键),但是有“—”符号,这代表时长音,例如5—(表示2分之一音符)的时长是6的两倍。如果表示全音符则为5— — —(3条杠),如果表示降低时间则在数字下面加—,例如8分音符:5,16分则加两条以此类推
从下往上读,这个表示以4分音符为1拍,每小节有4拍。
3 3:表示需要松开再按3键
表示不要松开,延音符,这样表示节拍清晰可见
在上小星星简谱讲了如何表示整倍数时间,接下来讲一下如何表示不是整倍数的时间,例如表示1.5个4分之一节拍,需要用到附点”.”,附点表示在原来的时基础上延长二分之一,例如第二节的第一拍为“i.”表示1.5个4分之一节拍。
七、蜂鸣器播放提示音
频率 = 1/f ,过500us翻转一次,1ms为一周期,频率 = 1/1ms = 1000hz
main.c
#include <REGX52.H> #include "Delay.h" #include "Key.h" #include "Nixie.h" #include "Buzzer.h" unsigned char KeyNum; void main() { Nixie(1,0); while(1) { KeyNum=Key(); if(KeyNum) { Buzzer_Time(100); Nixie(1,KeyNum); } } }
Buzzer.c
#include <REGX52.H> #include <INTRINS.H> //蜂鸣器端口: sbit Buzzer=P1^5; / * @brief 蜂鸣器私有延时函数,延时500us * @param 无 * @retval 无 */ void Buzzer_Delay500us() //@12.000MHz { unsigned char i; _nop_(); i = 247; while (--i); } / * @brief 蜂鸣器发声 * @param ms 发声的时长,范围:0~32767 * @retval 无 */ void Buzzer_Time(unsigned int ms) { unsigned int i; for(i=0;i<ms*2;i++) { Buzzer=!Buzzer; Buzzer_Delay500us(); } }
Nixie.c
#include <REGX52.H> #include "Delay.h" //数码管段码表 unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; / * @brief 数码管显示 * @param Location 要显示的位置,范围:1~8 * @param Number 要显示的数字,范围:段码表索引范围 * @retval 无 */ void Nixie(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(1); //显示一段时间 // P0=0x00; //段码清0,消影 }
八、蜂鸣器播放音乐
将对应的定时器初值和时间存入数组,通过访问数字的方式来使得蜂鸣器响应对应的频率,来奏响音乐,再读取对应的时间来获得使得频率响对应时长,再奏响一个频响对应时间后将定时器关闭一下,来使每个频响有间隔达到演奏音乐效果。
main.c
#include <REGX52.H> #include "Delay.h" #include "Timer0.h" //蜂鸣器端口定义 sbit Buzzer=P1^5; //播放速度,值为四分音符的时长(ms) #define SPEED 500 //音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号# #define P 0 #define L1 1 #define L1_ 2 #define L2 3 #define L2_ 4 #define L3 5 #define L4 6 #define L4_ 7 #define L5 8 #define L5_ 9 #define L6 10 #define L6_ 11 #define L7 12 #define M1 13 #define M1_ 14 #define M2 15 #define M2_ 16 #define M3 17 #define M4 18 #define M4_ 19 #define M5 20 #define M5_ 21 #define M6 22 #define M6_ 23 #define M7 24 #define H1 25 #define H1_ 26 #define H2 27 #define H2_ 28 #define H3 29 #define H4 30 #define H4_ 31 #define H5 32 #define H5_ 33 #define H6 34 #define H6_ 35 #define H7 36 //索引与频率对照表 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, }; //乐谱 unsigned char code Music[]={ //音符,时值, //1 P, 4, P, 4, P, 4, M6, 2, M7, 2, H1, 4+2, M7, 2, H1, 4, H3, 4, M7, 4+4+4, M3, 2, M3, 2, //2 M6, 4+2, M5, 2, M6, 4, H1, 4, M5, 4+4+4, M3, 4, M4, 4+2, M3, 2, M4, 4, H1, 4, //3 M3, 4+4, P, 2, H1, 2, H1, 2, H1, 2, M7, 4+2, M4_,2, M4_,4, M7, 4, M7, 8, P, 4, M6, 2, M7, 2, //4 H1, 4+2, M7, 2, H1, 4, H3, 4, M7, 4+4+4, M3, 2, M3, 2, M6, 4+2, M5, 2, M6, 4, H1, 4, //5 M5, 4+4+4, M2, 2, M3, 2, M4, 4, H1, 2, M7, 2+2, H1, 2+4, H2, 2, H2, 2, H3, 2, H1, 2+4+4, //6 H1, 2, M7, 2, M6, 2, M6, 2, M7, 4, M5_,4, M6, 4+4+4, H1, 2, H2, 2, H3, 4+2, H2, 2, H3, 4, H5, 4, //7 H2, 4+4+4, M5, 2, M5, 2, H1, 4+2, M7, 2, H1, 4, H3, 4, H3, 4+4+4+4, //8 M6, 2, M7, 2, H1, 4, M7, 4, H2, 2, H2, 2, H1, 4+2, M5, 2+4+4, H4, 4, H3, 4, H3, 4, H1, 4, //9 H3, 4+4+4, H3, 4, H6, 4+4, H5, 4, H5, 4, H3, 2, H2, 2, H1, 4+4, P, 2, H1, 2, //10 H2, 4, H1, 2, H2, 2, H2, 4, H5, 4, H3, 4+4+4, H3, 4, H6, 4+4, H5, 4+4, //11 H3, 2, H2, 2, H1, 4+4, P, 2, H1, 2, H2, 4, H1, 2, H2, 2+4, M7, 4, M6, 4+4+4, P, 4, 0xFF //终止标志 }; unsigned char FreqSelect,MusicSelect; void main() { Timer0Init(); while(1) { if(Music[MusicSelect]!=0xFF) //如果不是停止标志位 { FreqSelect=Music[MusicSelect]; //选择音符对应的频率 MusicSelect++; Delay(SPEED/4*Music[MusicSelect]); //选择音符对应的时值 MusicSelect++; TR0=0; Delay(5); //音符间短暂停顿 TR0=1; } else //如果是停止标志位 { TR0=0; while(1); } } } void Timer0_Routine() interrupt 1 { if(FreqTable[FreqSelect]) //如果不是休止符 { /*取对应频率值的重装载值到定时器*/ TL0 = FreqTable[FreqSelect]%256; //设置定时初值 TH0 = FreqTable[FreqSelect]/256; //设置定时初值 Buzzer=!Buzzer; //翻转蜂鸣器IO口 } }
Timer.c
#include <REGX52.H> / * @brief 定时器0初始化,1毫秒@12.000MHz * @param 无 * @retval 无 */ void Timer0Init(void) { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x18; //设置定时初值 TH0 = 0xFC; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0=1; EA=1; PT0=0; } /*定时器中断函数模板 void Timer0_Routine() interrupt 1 { static unsigned int T0Count; TL0 = 0x18; //设置定时初值 TH0 = 0xFC; //设置定时初值 T0Count++; if(T0Count>=1000) { T0Count=0; } } */
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/129761.html