蜂鸣器

无源蜂鸣器不能一直通电流,它内部置了线圈,要给他交流震荡

VCC高电平,只有蜂鸣器接口处为0才能驱动;白色三角是非门,左边给1/0右边反0/1

经典上代码
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Buzzer.h"
unsigned char KeyNum;
void main()
{
while(1)
{
KeyNum=Key();
if(KeyNum)
{
Buzzer_Time(1000);
Nixie(1,KeyNum);
}
}
}
Key.c
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
Nixie.c
#include <REGX52.H>
#include "Delay.h" //包含Delay头文件
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管显示子函数
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]; //段码输出
}
Buzzer.c
#include <REGX52.H>
#include "Delay.h"
#include <INTRINS.H>
//蜂鸣器端口:
sbit Buzzer=P2^5;
/**
* @brief 蜂鸣器私有延时函数,延时500ms
* @param 无
* @retval 无
*/
void Buzzer_Delay500us() //@11.0592MHz,专门为蜂鸣器写了一个
{
unsigned char i;
_nop_();
i = 227;
while (--i);
}
/**
* @brief 蜂鸣器发声
* @param ms,发声的时长
* @retval 无
*/
void Buzzer_Time(unsigned int ms)
{
//原来的Delay最小是1ms(半个周期),那么1个周期是2ms,能达到的蜂鸣器最大频率是1/2*0.1^3=500Hz,蜂鸣器标准提示音是1000Hz
//根据f=1/T,Delay(模块,不建议修改)的应该要更小,但是1已经是最小的
unsigned int i;
for(i=0;i<ms*2;i++)//用for循环是为了让蜂鸣器响的久一点
//*2的原因:现在的ms代表500us,不乘二,它只响ms/2毫秒,乘以二才是响ms毫秒
{
Buzzer=!Buzzer;//发声需要翻转两次io口
Buzzer_Delay500us();//半个周期500us,一个周期1000us,频率1000Hz=1/1000*0.1^6
}
}
Buzzer.h
#ifndef __Buzzer_H__
#define __Buzzer_H__
sbit Buzzer=P2^5;
void Buzzer_Time(unsigned int ms);
#endif
音乐
音符—>频率(Hz)—>周期(us)—>周期/2(us)—>取整—>重装数值(用到定时器)
周期=1/频率
周期/2:半个周期翻转一次
周期/2-小数点=取整
65535-取整=重装数值
用定时器操控频率
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Time0.h"
sbit Buzzer=P2^5;
unsigned int FreqTable[]={63628,63731};//存放每个音的重载数值
unsigned char FreqSelect;//对于数组FreqTable中每个数据对应的Index
void main()
{
Timer0Init();
while(1)
{
FreqSelect++;
Delay(500);//在中断里每个500ms自动切换到下一个音
}
}
void Timer0_Routine() interrupt 1//定时器初始化每隔1ms进行一次,所以每隔1ms中断一次
{
TL0 = FreqTable[FreqSelect]%256; //设置定时初值
TH0 = FreqTable[FreqSelect]/256; //设置定时初值
//跟子函数里的设置不同在于,之后的溢出都是这里管理的,子函数那只管理一次
Buzzer=!Buzzer; //直接翻转,一个周期是2*1ms(翻转两次才是一个周期),频率=1/2*1*0.1^3=500Hz
}
Timer0.c
#include <REGX52.H>
/**
* @brief 定时器0初始化,1ms@11.0592MH
* @param 无
* @retval 无
*/
void Timer0Init(void) //1毫秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01;
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
//TH0和TL0无关紧要,他们只决定第一次中断时间,因为溢出之后他们不清零,所以这里可以不改,只改主函数里的
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //允许中断
EA=1;
PT0=0;
}
/*
定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;//为了不丢失这个数字
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
*/