蜂鸣器


蜂鸣器

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

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;
	}
}
*/

文章作者: WB
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WB !
  目录