+本文为博主 LED-执棋困局,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!
> 发布人:LED-执棋困局
> 欢迎你为独创博主LED-执棋困局点赞❤❤❤+关注👍+收藏🌹+评论☺。系列专栏:CSDN-单片机学习系列🎁
> 我的格言是:“尽最大努力,做最好的自己!💪
版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章,CSDN独一份。
如需转载,还请通知一声噢⚠!
目录
一、频率计简介
1.1门铃打铃概述
设计要求:
1.通过按键控制门铃启动停止,按下第一个按键能启动和停止门铃打铃。
2.门铃打铃声音为叮咚叮咚。
3.每次发咚或每次发叮,持续时间为500ms。
4.发出叮咚时,可以用示波器检测到正确的波形。
1.2门铃打铃组成
以at89c51单片机为核心,内部使用定时器,一次定时250us,外接按键模块、蜂鸣器模块和示波器,按键模块负责控制蜂鸣器是否发声,蜂鸣器模块则负责发出叮咚叮咚。
1.3叮咚发声原理
我们应该知道,声音是一种信号,可用波形描述出来,不同声音其波形不同(频率/周期/振幅等不同),所以只有满足相应的波形,就能发出对应的声音。
下图为咚的波形图。通过网上资料查找,咚的频率大概为700hz,根据T=1/f得周期T=1428.6us,因为一个周期高低电平各占一半,电平反转时间为T/2=714.3us。
叮的频率大概在500hz,根据T=1/f得周期T=2000us,因为一个周期高低电平各占一半,电平反转时间为T/2=1000us。
1.4定时设置
at89c51单片机内部自带定时器,我们定时250us中断一次,对于咚声音来说,每714.3us电平反转一次,所以需要每中断3次让电平反转一次。对于叮声音来说,每1000us电平反转一次,所以需要每中断4次让电平反转一次。
二、仿真硬件设计
2.1声音硬件电路设计
2.1.1理论阐述
蜂鸣器广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。按照驱动方式的不同,分为有源蜂鸣器和无源蜂鸣器。这里的有源和无源不是指电源,而是振荡源。无源蜂鸣器要加500hz-4.5khz的脉冲频率信号驱动,有源蜂鸣器自带震荡源,加电就能响。
按构造方式的不同,可分为:电磁式蜂鸣器和压电式蜂鸣器;按封装的不同,可分为:DIP BUZZER(插针蜂鸣器)和SMDBUZZER(贴片式蜂鸣器);按电流的不同,可分为:直流蜂鸣器和交流蜂鸣器。
三极管导通:Ve-0.7>Vc
饱和条件:电流Ib>Iec/β
Iec=(5-0.2-2)/1K=3mA,已知β=100,则Iec/β=30uA,饱和条件为电流Ib>30uA,
所以R47max=(5-0.7)/30=143K
89C52的IO口输入电流最大理论值是25mA,推荐不要超过6mA,图中取的是经验值。
buzz端高电平时,三极管无法导通,反之可以导通。当能导通时,电流流经蜂鸣器,使其发生声响。
2.1.2电路模块
2.2按键硬件设计
2.3仿真图展现
三、软件程序设计
3.1总体软件设计思路
定时器定时T0,定时250us中断一次,可以定义两个累加变量判断中断次数,达到一定次数就执行电平反转,同时考虑到有叮咚两种声音,可以定义一个标志位来判断发咚还是叮,此外,引用按键模块,书写按键服务函数,通过返回值判断按键是否按下,用TR0来控制蜂鸣器是否发出声音。
3.2主程序程序设计
定义uc500hz、uc700hz用于控制中断次数。
定义cnd用于控制发出叮/咚声音的总时间。
定义flag用于控制蜂鸣器发咚还是发叮。
#include <reg51.h>
#include "key.h"
void Timer0_Init();
void key_service();
unsigned int uc500Hz=0;
unsigned int uc700Hz=0;
unsigned int cnd=0;
unsigned int flag=0;
sbit button=P3^7;
void main()
{
Timer0_Init();
while(1)
{
key_service();
}
}
3.3定时器初始化程序设计
void Timer0_Init(void) //250微秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x06; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TF0 = 0; //清除TF0标志
ET0=1;
EA=1;
}
3.4中断程序设计
定时一次250us,即250us中断一次,一种声音要持续时间为500ms=500000us,中断次数为500000us/250us=2000,所以cnd要累加到2000,flag取反。flag=0时,蜂鸣器发咚;flag≠0时,蜂鸣器发叮。当满足uc700hz=3时,说明中断了3次(750ms),发咚;当满足uc500hz=4时,说明中断了4次(1000ms),发叮;
void ISR_timers() interrupt 1
{
cnd++;
if(cnd>=2000) //先咚发声时间为500ms,然后叮发声时间为500ms,
//接着又轮到咚,过后又是叮,不断交替发声,一次500ms
{
flag=~flag; //flag用来判断声音发叮还是咚
cnd=0;
}
if(!flag) //咚
{
uc700Hz++;
if(uc700Hz>=3) //3次,咚
{
uc700Hz=0;
button=~button;//电平反转
}
}
if(flag) //钉
{
uc500Hz++;
if(uc500Hz>=4) //4次,叮
{
uc500Hz=0;
button=~button;//电平反转
}
}
TL0 = 0x06; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
}
3.5按键程序设计
引用key_scan.h按键模块,通过控制TR0,来实现对蜂鸣器是否发声的功能。
void key_service()
{
switch(key())
{
case 3:TR0=~TR0;break;
default:break;
}
}
#include "key_scan.h"//独立键盘头文件
#include "delay.h"//延时头文件
/******************************************************************************************
函数名:key
功能: 独立键盘函数
参数: 无
返回值:unsigned char
******************************************************************************************/
unsigned char key_scan()//独立键盘按键函数
{
unsigned char temp,temp2;
static unsigned char keynum=20;
KEYPIO=0xf0;//1为输入 0位输出 令高4位为1 低4位为0
temp=KEYPIO;
if(temp!=0xf0)//判断是否按下按键
{
delay(10);//消抖延时10ms
if(temp!=0xf0)//再次判断是否按下按键
{
temp=KEYPIO&0xf0;//确定行
KEYPIO=0x0f;//反转
temp2=KEYPIO&0x0f;//确定列
}
}
switch(temp+temp2)
{
case 0xee:keynum=1;break;
case 0xed:keynum=2;break;
case 0xeb:keynum=3;break;
case 0xe7:keynum=4;break;
case 0xde:keynum=5;break;
case 0xdd:keynum=6;break;
case 0xdb:keynum=7;break;
case 0xd7:keynum=8;break;
case 0xbe:keynum=9;break;
case 0xbd:keynum=0;break;
case 0xbb:keynum=10;break;
case 0xb7:keynum=11;break;
case 0x7e:keynum=12;break;
case 0x7d:keynum=13;break;
case 0x7b:keynum=14;break;
case 0x77:keynum=15;break;
default:break;
}
return keynum;
}
这是头文件key_scan.h,需要对key_scan()声明,对P3宏定义。
#ifndef __KEY_SCAN_H__
#define __KEY_SCAN_H__
#include <reg51.h>//51头文件
#define KEYPIO P3 //矩阵键盘两端所接的IO口
unsigned char key_scan();//独立键盘函数声明
#endif
3.6延时模块
delay.c
#include "delay.h"
/******************************************************************************************
函数名:delay
功能:延时函数
参数:unsigned char xms
返回值:无
******************************************************************************************/
void delay(unsigned char xms)
{
unsigned char i,j;
for(i=xms;i>0;i--)
for(j=124;j>0;j--);
}
delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void delay(unsigned char xms);//延时函数声明
#endif
四、波形仿真测量
4.1示波器调用
以下是调用示波器的步骤。
4.2示波器用法
示波器最多同时测4个波形。①:通过调电压大小使波形振幅发生变化。②:波形整体上下移动。③:波形整体左右移动。④:调节波形宽度,但频率不会发生改变。
五、结果与扩展
5.1结果展现
结果:完成设计要求,按键灵敏度高,蜂鸣器能发出叮咚声,无噪音,波形正确。
示波器用的是黄色A接口,第一个图是咚的波形图,第二个是叮的波形图。
5.2扩展功能
本次实战,主要是手动的门铃打铃,读者可以制作智能门铃打铃,采用红外线,当有人时,红外线会扫描到,从而发出叮咚声;没人时,不会发出声音。这个跟现实生活中有人来店里,机器会发出欢迎光临声音功能是相似的。
六、总结
本次介绍了门铃打铃的基本理论知识,学习计算周期T、每种声音中断次数,同时提供模块代码和仿真图,帮助大家理解相关编码思路。
hi!我是博主LED-执棋困局🔥,喜欢或期待更好作品的,可以关注一下我🙏🙏🙏,带你们一起进步,另外欢迎大家的点评😊!!!
下一文:制作pwn波形模块,下集更精彩。