51单片机累计主循环次数实现独立按键

发布者:婉如Chanel最新更新时间:2021-11-22 来源: eefocus关键字:51单片机  独立按键 手机看文章 扫描二维码
随时随地手机看文章

一、使用proteus绘制简单的电路图,用于后续仿真

二、编写程序


/********************************************************************************************************************

---- @Project: Independent-KEY

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200505

---- @ModifiedTime: 20200505

---- @Description: 有两个独立按键,每按一个独立按键,蜂鸣器发出“滴”的一声后就停。

---- 单片机:AT89C52

********************************************************************************************************************/

#include "reg52.h"

 

/*——————宏定义——————*/

#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   /*1ms timer calculation method in 12Tmode*/

 

#define const_voice_short  80   /*蜂鸣器短叫的持续时间*/

 

#define const_key_time1   1000  /*按键去抖动延时的时间*/

#define const_key_time2   1000  /*按键去抖动延时的时间*/

 

/*——————变量函数定义及声明——————*/

/*定义按键S1*/

sbit Key_S1 = P0^0;

/*定义按键S2*/

sbit Key_S2 = P0^1;

/*定义蜂鸣器*/

sbit BUZZER = P2^7;

 

unsigned char ucKeySec = 0;   /*被触发的按键编号*/

 

unsigned int  uiKeyTimeCnt1 = 0; /*按键去抖动延时计数器*/

unsigned char ucKeyLock1 = 0; /*按键触发后自锁的变量标志*/

 

unsigned int  uiKeyTimeCnt2 = 0; /*按键去抖动延时计数器*/

unsigned char ucKeyLock2 = 0; /*按键触发后自锁的变量标志*/

 

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

 

 

/**

* @brief  定时器0初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_T0(void)

{

TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

}

/**

* @brief  定时器0中断函数

* @param  无

* @retval 无

**/

void ISR_T0(void) interrupt 1

{

TF0 = 0;  /*清除中断标志*/

  TR0 = 0; /*关中断*/

if(0 != uiVoiceCnt)

{

uiVoiceCnt --;

BUZZER = 0;

}

else

{

BUZZER = 1;

}

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

  TR0 = 1; /*开中断*/

}

/**

* @brief  外围初始化函数

* @param  无

* @retval 初始化外围

**/

void Init_Peripheral(void)

{

ET0 = 1;/*允许定时中断*/

TR0 = 1;/*启动定时中断*/

EA = 1;/*开总中断*/

 

}

 

/**

* @brief  初始化函数

* @param  无

* @retval 初始化单片机

**/

void Init(void)

{

Init_T0();

BUZZER = 1;

}

/**

* @brief  扫描按键函数

* @param  无

* @retval 独立按键扫描的详细过程:

* 第一步:平时没有按键被触发时,按键的自锁标志和去抖动延时计数器一直被清零。

* 第二步:一旦有按键被按下,去抖动延时计数器开始累加,在还没累加到

*         阀值const_key_time1时,如果在这期间由于受外界干扰或者按键抖动,而使

*         IO口突然瞬间触发成高电平,这个时候马上又把延时计数器uiKeyTimeCnt1

*         清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。

*         以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。

* 第三步:如果按键按下的时间超过了阀值const_key_time1,则触发按键,把编号ucKeySec赋值。

*         同时,马上把自锁标志ucKeyLock1置位,防止按住按键不松手后一直触发。

* 第四步:等按键松开后,自锁标志ucKeyLock1及时清零,为下一次自锁做准备。

* 第五步:以上整个过程,就是识别按键IO口下降沿触发的过程。

**/

void Key_Scan(void)

{

/*扫描S1*/

if(Key_S1 == 1) /*如果没有键按下(高电平),将一些标志位及时清零*/

{

ucKeyLock1 = 0;/*自锁标志位清0*/

uiKeyTimeCnt1 = 0;/*按键去抖动延时计数器清零*/

}

else if(ucKeyLock1 == 0) /*如果有按键按下,且是第一次按下*/

{

++ uiKeyTimeCnt1;/*延时计数器计数*/

if(uiKeyTimeCnt1 > const_key_time1)

{

uiKeyTimeCnt1 = 0;

ucKeyLock1 = 1;/*自锁标志位置位,避免一直触发*/

ucKeySec = 1; /*触发S1*/

}

}

/*扫描S2*/

if(Key_S2 == 1) /*如果没有键按下(高电平),将一些标志位及时清零*/

{

ucKeyLock2 = 0;/*自锁标志位清0*/

uiKeyTimeCnt2 = 0;/*按键去抖动延时计数器清零*/

}

else if(ucKeyLock2 == 0) /*如果有按键按下,且是第一次按下*/

{

++ uiKeyTimeCnt2;/*延时计数器计数*/

if(uiKeyTimeCnt2 > const_key_time2)

{

uiKeyTimeCnt2 = 0;

ucKeyLock2 = 1;/*自锁标志位置位,避免一直触发*/

ucKeySec = 2; /*触发S2*/

}

}

}

/**

* @brief  按键服务函数

* @param  无

* @retval 根据扫描得到的值,进行数据处理

**/

void key_Service(void)

{

switch(ucKeySec)

{

case 1: /*S1按下*/

uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/

ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/

break;

case 2:/*S2按下*/

uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/

ucKeySec = 0; 

break;

}

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i   {

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

          {

             ; /*一个分号相当于执行一条空语句*/

          }

   }

}

/*——————主函数——————*/

/**

* @brief  主函数

* @param  无

* @retval 实现LED灯闪烁

**/

void main()

{

/*单片机初始化*/

Init();

/*延时,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定*/

Delay_Long(100);

/*单片机外围初始化*/

Init_Peripheral();

while(1)

{

/*扫描按键*/

Key_Scan();

/*按键服务函数*/

key_Service();

}

}

 

三、仿真实现

关键字:51单片机  独立按键 引用地址:51单片机累计主循环次数实现独立按键

上一篇:51单片机累计定时中断次数实现独立按键
下一篇:51单片机累计中断次数使LED灯闪烁

推荐阅读最新更新时间:2024-11-16 20:24

51单片机P0口上拉电阻的阻值问题
如果是驱动led,那么用1K左右的就行了。如果希望亮度大一些,电阻可减小,最小不要小于200欧姆,否则电流太大;如果希望亮度小一些,电阻可增大,增加到多少呢,主要看亮度情况,以亮度合适为准,一般来说超过3K以上时,亮度就很弱了,但是对于超高亮度的LED,有时候电阻为10K时觉得亮度还能够用。通常就用1k的。 对于驱动光耦合器,如果是高电位有效,即耦合器输入端接端口和地之间,那么和LED的情况是一样的;如果是低电位有效,即耦合器输入端接端口和VCC之间,那么除了要串接一个1——4.7k之间的电阻以外,同时上拉电阻的阻值就可以用的特别大,用100k——500K之间的都行,当然用10K的也可以,但是考虑到省电问题,没有必要用那么小的
[单片机]
51单片机-指令周期与LED闪烁
之前讲了如何点亮LED,包括硬件电路和程序,今天说一下如何让LED闪烁。单片机控制LED闪烁有两种方法,一种是软件延时,另一种是定时器中断。因为涉及到单片机指令集的问题,还有一些简单的C语言,今天只讲第一种。 先说指令集,早期的51单片机都是复杂指令集,因为沿用的习惯现在用的STC89C52单片机也是复杂指令集,和复杂指令集对应的,就是精简指令集,常见的有AVR和430单片机。 这两种指令集的区别是啥?最明显的就是一条指令执行的时间,举个例子:51单片机和AVR单片机都外接一个12M的晶体,一个时钟周期是1/12M=1/12US,执行一条单周期指令(多周期指令不考虑)需要多少时间? 51单
[单片机]
学<font color='red'>51单片机</font>-指令周期与LED闪烁
一种简单串行鼠标控制的51单片机实现
鼠标是一种快速定位器,通过移动鼠标可以快速定位屏幕上的对象,是计算机图形界面交互的必用外部设备。通常,鼠标通过微机中的串口或PS/2鼠标插口与主机连接。当在平面上移动鼠标时,通过机械或光学的方法把鼠标滚轮移动的距离和方向转换成脉冲信号传送给计算机,计算机鼠标驱动程序将脉冲个数转换成鼠标的水平方向和垂直方向的位移量,从而控制显示屏上光标箭头随鼠标的移动而移动。根据此原理,我们可利用鼠标的上位机驱动程序来设计测控系统中的编码器读取软件。 1 串行鼠标的原理及数据协议 鼠标一般划分为以下功能模块:微控制器、 按键检测、位置移动检测、RS232信号产生、5V电源产生器。串行鼠标的功能框图如图1所示。 微软公司与Mouse S
[单片机]
一种简单串行鼠标控制的<font color='red'>51单片机</font>实现
45-基于51单片机的甲醛浓度检测报警系统
具体实现功能 系统由STC89C52单片机+ZE08-CH2O甲醛传感器+LCD1602液晶显示屏+按键+蜂鸣器+指示灯+电源构成。 具体功能: 1、甲醛传感器测得甲醛数据后经过单片机处理,由LCD1602实时显示; 2、可通过按键设置甲醛报警阈值; 3、测得的甲醛浓度超过报警阈值时,开始声光报警。 设计背景 如今自动化、信息化程度越来越高,随着社会的发展、科技的进步以及人们生活水平的逐步提高,各种方便于生活的自动控制系统开始进入了人们的生活,同时也标志了自动控制领域成为了数字化时代的一员。以单片机为核心的自动门系统就是其中之一。它实用性强,功能齐全,技术先进,使人们相信这是科技进步的成果。它更让人类懂得,数字
[单片机]
45-基于<font color='red'>51单片机</font>的甲醛浓度检测报警系统
51单片机DS18B20温度传感四位数码管显示报警
仿真原理图如下 全部资料分享,可设置温度报警的上下限,5641四位共阳数码管显示温度,自己曾经做的设计,实测可行,提供给有需要的人 单片机源程序如下: #include AT89X52.h #define uint unsigned int #define uchar unsigned char //宏定义 #define SET P3_1 //定义调整键 #define DEC P3_2 //定义减少键 #define ADD P3_3 //定义增加键 #define BEEP P3_6 //定义蜂
[单片机]
<font color='red'>51单片机</font>DS18B20温度传感四位数码管显示报警
51单片机的定时器与中断
一、中断及定时器工作原理 1、中断概念: 1 CPU处理事件A发生事件B进行处理(中断产生) 2 CPU暂时中断当前工作,转去处理事件B(中断响应与中断服务) 3 待CPU处理完B,再回来处理事件A(中断返回) 4 51不支持中断嵌套 图释: 注意:中断服务不超过20行,尽量简短,不要进行复杂的比较,延时运算!可以进行简单比较,标志位,赋值的处理 保存主程序服务状态(保护现场):push:入栈 保存工作状态 恢复工作状态 pop:出栈 89C51:5个中断源 89C52:8个中断源 2、 可以看出,003H——00BH中有8个字节,显然是不够程序存放的,着八个字节中存放跳转指令 在ARM中,此表叫做中断向量表,在ARM
[单片机]
基于W78E51单片机的自动拨号器设计
自动拨号器是一种智能化的报警监控装置,它以单片机为核心器件,利用无线寻呼和程控电话可随时将警情发送给指定的接收机。它配备不同的传感器后,不但可以对有毒气体泄漏、家中被盗等情况进行报警,而且还可对通信设备及电源故障的发生进行告警,可广泛应用于仓库、小型商店、无人值守通信台站的监测以及家庭防盗、煤气报警等。 工作原理 自动拨号器按功能的不同可分为可编码型和简易型两种。可编码型自动拨号器可人为设置、更改接收机号码,使用方便灵活;简易型自动拨号器的接收机号码已写入CPU的程序存储器中,具有成本低廉、稳定可靠的特点,缺点是不能人为更改接收机号码,需通过编程器写入,但成本较可编码型低。以下分别介绍这两种拨号器的工作原理。 可编
[单片机]
基于W78E<font color='red'>51单片机</font>的自动拨号器设计
51单片机的外部中断触发方式
51单片机的外部中断有两种触发方式可选:电平触发和边沿触发。选择电平触发时,单片机在每个机器周期检查中断源口线,检测到低电平,即置位中断请求标志,向CPU请求中断。选择边沿触发方式时,单片机在上一个机器周期检测到中断源口线为高电平,下一个机器周期检测到低电平,即置位中断标志,请求中断。 这个原理很好理解。但应用时需要特别注意的几点: 1) 电平触发方式时,中断标志寄存器不锁存中断请求信号。也就是说,单片机把每个机器周期的S5P2采样到的外部中断源口线的电平逻辑直接赋值到中断标志寄存器。标志寄存器对于请求信号来说是透明的。这样当中断请求被阻塞而没有得到及时响应时,将被丢失。换句话说,要使电平触发的中断被CPU响应并执行,必须保证外部中
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved