您的位置 首页 电子

第五节:蜂鸣器的驱动程序

开场白:上一节讲了利用累计定时中断次数实现LED灯闪烁,这个例子同时也第一次展示了我最完整的实战程序框架:用switch语句实现状态机,外

开场白:

上一节讲了使用累计守时中止次数完成LED灯闪耀,这个比方一起也榜首次展现了我最完好的实战程序结构:用switch句子完成状态机,外加守时中止。这个结构看似简略,实际上便是那么简略。我做的一切开发项目都是根据这个简略结构,可是十分好用。上一节只需一个单使命的LED灯在闪耀,这节开端,咱们多添加一个蜂鸣器报警的使命,要教会我们四个知识点:

榜首点:蜂鸣器的驱动程序结构编写。

第二点:多使命处理的程序结构。

第三点:怎么操控蜂鸣器声响的长叫和短叫。

第四点:怎么知道1秒钟需求多少个守时中止,也便是怎么按份额批改时刻精度。

具体内容,请看源代码解说。

(1)硬件渠道:根据朱兆祺51单片机学习板

(2)完成功用:一起跑两个使命,榜首个使命让一个LED灯1秒钟闪耀一次。第二个使命让蜂鸣器在前面3秒产生一次短叫报警,在后面6秒产生一次长叫报警,重复循环。

(3)源代码解说如下:

#include “REG52.H”

/* 注释一:

* 怎么知道1秒钟需求多少个守时中止?

* 这个需求编写一段小程序测验,得到测验的成果后再按份额批改。

* 过程:

* 榜首步:在程序代码上先写入1秒钟大约需求200个守时中止。

* 第二步:根据以上1秒钟的基准,编写一个60秒的简略测验程序(假如编写超越

* 60秒的时刻,这个精度还会更高)。比方,编写一个用蜂鸣器的声响来辨认计时的

* 开端和中止的测验程序。

* 第三步:把程序烧录进单片机后,上电开端测验,手上同步翻开手机里的秒表。

* 假如单片机只是跑了27秒。

* 第四步:那么终究得出1秒钟需求的守时中止次数是:const_time_1s=(200*60)/27=444

*/

#define const_time_05s 222 //0.5秒钟的时刻需求的守时中止次数

#define const_time_1s 444 //1秒钟的时刻需求的守时中止次数

#define const_time_3s 1332 //3秒钟的时刻需求的守时中止次数

#define const_time_6s 2664 //6秒钟的时刻需求的守时中止次数

#define const_voice_short 40 //蜂鸣器短叫的持续时刻

#define const_voice_long 200 //蜂鸣器长叫的持续时刻

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void led_flicker();

void alarm_run();

void T0_time(); //守时中止函数

sbit beep_dr=P2^7; //蜂鸣器的驱动IO口

sbit led_dr=P3^5; //LED灯的驱动IO口

unsigned char ucLedStep=0; //LED灯的过程变量

unsigned int uiTimeLedCnt=0; //LED灯计算守时中止次数的延时计数器

unsigned char ucAlarmStep=0; //报警的过程变量

unsigned int uiTimeAlarmCnt=0; //报警计算守时中止次数的延时计数器

unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的持续时刻计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

led_flicker(); //榜首个使命LED灯闪耀

alarm_run(); //第二个使命报警器守时报警

}

}

void led_flicker() //第三区 LED闪耀应用程序

{

switch(ucLedStep)

{

case 0:

if(uiTimeLedCnt>=const_time_05s) //时刻到

{

uiTimeLedCnt=0; //时刻计数器清零

led_dr=1; //让LED亮

ucLedStep=1; //切换到下一个过程

}

break;

case 1:

if(uiTimeLedCnt>=const_time_05s) //时刻到

{

uiTimeLedCnt=0; //时刻计数器清零

led_dr=0; //让LED灭

ucLedStep=0; //回来到上一个过程

}

break;

}

}

void alarm_run() //第三区 报警器的应用程序

{

switch(ucAlarmStep)

{

case 0:

if(uiTimeAlarmCnt>=const_time_3s) //时刻到

{

uiTimeAlarmCnt=0; //时刻计数器清零

/* 注释二:

* 只需变量uiVoiceCnt不为0,蜂鸣器就会在守时中止函数里发动鸣叫,而且自减uiVoiceCnt

* 直到uiVoiceCnt为0时才中止鸣叫。因而操控uiVoiceCnt变量的巨细便是操控声响的长短。

*/

uiVoiceCnt=const_voice_short; //蜂鸣器短叫

ucAlarmStep=1; //切换到下一个过程

}

break;

case 1:

if(uiTimeAlarmCnt>=const_time_6s) //时刻到

{

uiTimeAlarmCnt=0; //时刻计数器清零

uiVoiceCnt=const_voice_long; //蜂鸣器长叫

ucAlarmStep=0; //回来到上一个过程

}

break;

}

}

void T0_time() interrupt 1

{

TF0=0; //铲除中止标志

TR0=0; //关中止

if(uiTimeLedCnt<0xffff) //设定这个条件,避免uiTimeLedCnt超范围。

{

uiTimeLedCnt++; //LED灯的时刻计数器,累加守时中止的次数,

}

if(uiTimeAlarmCnt<0xffff) //设定这个条件,避免uiTimeAlarmCnt超范围。

{

uiTimeAlarmCnt++; //报警的时刻计数器,累加守时中止的次数,

}

/* 注释三:

* 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?

* 由于放在守时中止里,能确保蜂鸣器的声响长度是共同的,

* 假如放在main循环里,声响的长度就有或许遭到某些有必要

* 趁热打铁的使命搅扰,得不到及时呼应,影响声响长度的共同性。

*/

if(uiVoiceCnt!=0)

{

uiVoiceCnt–; //每次进入守时中止都自减1,直到等于零中止。才中止鸣叫

beep_dr=0; //蜂鸣器是PNP三极管操控,低电平就开端鸣叫。

}

else

{

; //此处多加一个空指令,想保持跟if括号句子的数量对称,都是两条指令。不加也能够。

beep_dr=1; //蜂鸣器是PNP三极管操控,高电平就中止鸣叫。

}

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中止

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于履行一条空句子

}

}

}

void initial_myself() //榜首区 初始化单片机

{

beep_dr=1; //用PNP三极管操控蜂鸣器,输出高电平时不叫。

led_dr=0; //LED灭

TMOD=0x01; //设置守时器0为工作方式1

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

}

void initial_peripheral() //第二区 初始化外围

{

EA=1; //开总中止

ET0=1; //答应守时中止

TR0=1; //发动守时中止

}

总结陈词:

本节程序现已展现了一个多使命处理的基本思路,假如要完成一个独立按键检测,能不能也依照这种思路来处理呢?欲知概况,请听下回分解—–在主函数中使用累计主循环次数来完成独立按键的检测。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/262128.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部