单片机
返回首页

51单片机实现两个独立按键的组合按键触发

2021-11-22 来源:eefocus

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

二、编写程序


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

---- @Project: Independent-KEY

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200506

---- @ModifiedTime: 20200506

---- @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_time12   60  /*按键去抖动延时的时间*/

 

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

/*定义按键S1*/

sbit Key_S1 = P0^0;

/*定义按键S2*/

sbit Key_S2 = P0^1;

/*定义蜂鸣器*/

sbit BUZZER = P2^7;

 

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

 

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

unsigned char ucKeyLock12 = 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  外围初始化函数

* @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_time12时,如果在这期间由于受外界干扰或者按键抖动,而使

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

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

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

* 第三步:如果按键按下的时间超过了阀值const_key_time12,马上把自锁标志ucKeyLock12置位,

*         防止按住按键不松手后一直触发。并把编号ucKeySec赋值。 组合按键触发

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

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

**/

void Key_Scan(void)

{

/*扫描S1,S2*/

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

{

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

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

}

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

{

uiKeyTimeCnt12 ++;

if(uiKeyTimeCnt12 > const_key_time12)

{

uiKeyTimeCnt12 = 0;

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

ucKeySec = 1; /*触发标志1*/

}

}

}

/**

* @brief  按键服务函数

* @param  无

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

**/

void key_Service(void)

{

switch(ucKeySec)

{

case 1: 

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

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

break;

}

}

/**

* @brief  定时器0中断函数

* @param  无

* @retval 无

**/

void ISR_T0(void) interrupt 1

{

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

  TR0 = 0; /*关中断*/

/*扫描按键*/

Key_Scan();

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 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_Service();

}

}

 

三、仿真实现

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 用数字电路CD4069制作的万能遥控轻触开关

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • RS-485基础知识:处理空闲总线条件的两种常见方法

    相关电子头条文章