历史上的今天
返回首页

历史上的今天

今天是:2024年11月12日(星期二)

正在发生

2021年11月12日 | 51单片机实现按住一个独立按键不松手的连续步进触发

2021-11-12 来源:eefocus

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

二、编写程序


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

---- @Project: Independent-KEY

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200507

---- @ModifiedTime: 20200507

---- @Description: 两个独立按键S1和S2,S1键作为加键。S2键做为减键。每按一次S1键则被设置参数uiSetNumber自加1。如果按住S1键不松手超过1秒钟,被设置参数uiSetNumber以每0.25秒的时间间隔往上自加1,一直加到20为止。每按一次S5键则被设置参数uiSetNumber自减1。如果按住S2键不松手超过1秒钟,被设置参数uiSetNumber以每0.25秒的时间间隔往下自减1,一直减到0为止。当被设置参数uiSetNumber小于10的时候,LED灯灭;当大于或者等于10的时候,LED灯亮。

---- 单片机: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  60    /*按键去抖动延时的时间*/

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

 

#define const_time_0_25s  200    /*0.25秒钟的时间需要的定时中断次数*/

#define const_time_1s   800     /*1秒钟的时间需要的定时中断次数*/

 

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

/*定义按键S1*/

sbit Key_S1 = P0^0;

/*定义按键S2*/

sbit Key_S2 = P0^1;

/*定义蜂鸣器*/

sbit BUZZER = P2^7;

/*定义LED*/

sbit LED = P3^5;

 

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

 

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

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

unsigned char uiKeyCtntyCnt1=0; /*按键连续触发的间隔延时计数器*/

 

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

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

unsigned char uiKeyCtntyCnt2=0; /*按键连续触发的间隔延时计数器*/

 

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

 

unsigned int  uiSetNumber=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_time1时,如果在这期间由于受外界干扰或者按键抖动,而使

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

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

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

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

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

* 第四步:如果此时触发了一次按键后,一直不松手,去抖动延时计时器继续累加,直到超过了1秒钟。进入连续触发模式的程序

* 第五步:在连续触发模式的程序中,连续累加延时计数器开始累加,每0.25秒就触发一次。

* 第六步:等按键松开后,自锁标志ucKeyLock1和两个延时计时器及时清零,为下一次自锁做准备。

**/

void Key_Scan(void)

{

/*扫描S1*/

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

{

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

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

uiKeyCtntyCnt1 = 0; /*连续累加的时间间隔延时计数器清零*/

}

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

{

uiKeyTimeCnt1 ++;

if(uiKeyTimeCnt1 > const_key_time1)/*判定按下*/

{

uiKeyTimeCnt1 = 0;

ucKeyLock1 = 1;

ucKeySec = 1;    /*触发S1*/

}

}

else if(uiKeyTimeCnt1 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/

{

uiKeyTimeCnt1 ++;

}

else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/

{

uiKeyCtntyCnt1 ++;/*连续触发延时计数器累加*/

if(uiKeyCtntyCnt1 > const_time_0_25s)/*按住没松手,每0.25秒就触发一次*/

{

uiKeyCtntyCnt1 = 0;

ucKeySec = 1;    /*触发S1*/

}

}

/*扫描S2*/

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

{

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

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

uiKeyCtntyCnt2 = 0; /*连续累加的时间间隔延时计数器清零*/

}

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

{

uiKeyTimeCnt2 ++;

if(uiKeyTimeCnt2 > const_key_time2)/*判定按下*/

{

uiKeyTimeCnt2 = 0;

ucKeyLock2 = 1;

ucKeySec = 2;    /*触发S2*/

}

}

else if(uiKeyTimeCnt2 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/

{

uiKeyTimeCnt2 ++;

}

else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/

{

uiKeyCtntyCnt2 ++;/*连续触发延时计数器累加*/

if(uiKeyCtntyCnt2 > const_time_0_25s)/*按住没松手,每0.25秒就触发一次*/

{

uiKeyCtntyCnt2 = 0;

ucKeySec = 2;    /*触发S2*/

}

}

 

}

/**

* @brief  按键服务函数

* @param  无

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

**/

void key_Service(void)

{

switch(ucKeySec)

{

case 1: /*S1,连续加*/

uiSetNumber ++;/*被设置的参数连续往上加*/

if(uiSetNumber > 20)/*最大20*/

{

uiSetNumber = 20;

}

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

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

break;

case 2: /*S2,连续减*/

uiSetNumber --;/*被设置的参数连续往下减*/

if(uiSetNumber > 20)/*最小0,0 - 1 = 0xff > 20*/

{

uiSetNumber = 0;

}

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

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

break;

}

}

/**

* @brief  LED函数

* @param  无

* @retval 控制LED亮灭

**/

void Led_Run(void)  /*led灯的应用程序*/

{

   if(uiSetNumber < 10)  /*如果被设置的参数uiSetNumber小于10,LED灯则灭。否则亮。*/

   {

      LED = 0;  /*灭*/

   }

   else

   {

      LED = 1;  /*亮*/

   }

}

/**

* @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();

/*LED函数*/

Led_Run();

}

}

 

三、仿真实现

推荐阅读

史海拾趣

杰力(EMC)公司的发展小趣事

随着环保意识的不断提高和可持续发展理念的普及,杰力也开始注重环保和可持续发展方面的工作。公司采用环保材料和生产工艺,降低产品对环境的污染和破坏。同时,杰力还积极参与各类环保公益活动和社会责任项目,为推动电子行业的可持续发展做出贡献。这些努力使得杰力在行业中树立了良好的环保形象和社会责任感。

极海半导体(Geehy)公司的发展小趣事

杰力(EMC)公司成立于XXXX年,由一群具有丰富电子行业经验的专业人士创立。公司初期专注于功率组件和集成电路(IC)的设计与开发,以满足不断增长的电子市场需求。通过引进先进的生产设备和工艺,杰力迅速建立起一条高效的生产线,并开始为一些小型电子厂商提供定制化的产品。随着产品质量的不断提升和客户口碑的积累,杰力逐渐在市场中树立了良好的品牌形象。

Abracon公司的发展小趣事

为了保持市场竞争力,杰力不断投入研发资源,致力于技术创新和产品升级。公司成功研发出多款高性能、低功耗的功率组件和集成电路产品,并获得了多项专利。这些产品不仅满足了客户对高品质电子元件的需求,还推动了整个电子行业的发展。同时,杰力还密切关注市场动态和技术趋势,不断调整产品策略,以适应市场的变化。

Beta Dyne Inc公司的发展小趣事

随着国内市场的饱和,Beta Dyne开始将目光投向海外市场。公司制定了一套完整的国际化战略,包括在海外设立研发中心、建立销售渠道以及与当地企业建立合作关系等。通过不断的努力,Beta Dyne的产品逐渐打入国际市场,公司的知名度和影响力也得到了显著提升。

FOCI Fiber Optic Communications Inc公司的发展小趣事

随着国内市场的饱和,Beta Dyne开始将目光投向海外市场。公司制定了一套完整的国际化战略,包括在海外设立研发中心、建立销售渠道以及与当地企业建立合作关系等。通过不断的努力,Beta Dyne的产品逐渐打入国际市场,公司的知名度和影响力也得到了显著提升。

永源微电子(APM)公司的发展小趣事

随着产品线的拓展和技术实力的增强,永源微电子开始积极拓展市场。公司在台湾、深圳、香港、无锡等地设立了研发与销售中心,通过多渠道的市场推广和品牌建设活动,不断提升“APM”品牌的知名度和影响力。同时,永源微电子还积极参加国内外电子行业的展会和交流活动,与业界同行建立了广泛的合作关系,进一步拓展了公司的市场版图。

问答坊 | AI 解惑

万用表的使用方法

万用表万用表具有用途多,量程广,使用方便等优点,是电子测量中最常用的工具。它可以用来测量电阻,交直流电压和直流电压。有的万用表还可以测量晶体管的主要参数及电容器的电容量等。掌握万用表的使用方是电子技术的一项基本技能。   常见的多 ...…

查看全部问答>

欧姆龙PLC中断问题

欧姆龙PLC如何实现中断,从那里进入及退出,请高人指点!…

查看全部问答>

请问在wince里怎样用wifi发送特定数据

请问在wince里怎样用wifi发送特定数据 有人说就是socket编程,我没想明白,难道系统会自动调用wifi? 还请各位前辈指点迷津!…

查看全部问答>

学习AD0809,所以做一个数字电压表!

想学习一下AD,打算仿真做一个数字电压表,测量0~5V输出0~255,通过数码管显示,AD用的0809,模拟输入采用一个1K滑动变阻器连接到IN0(不知道这种做法是否可行?)现在的问题是,改变滑动变阻器的值,数码管的值有变化,但是并不是有规律地增大或 ...…

查看全部问答>

ST选型

请问谁清楚ST的哪个8位机有2个PWM,3个定时器,10路ADC,34个I/O(含10个AD口) ,是用来做电源的。wendellyang@163.com…

查看全部问答>

热电堆 信号选择

小弟最近想做一个用于微波炉的温度测量的红外探测模块。由于以前都没有做过项目,所以经验非常少,现在我苦于热电堆型号的挑选。         网上看了看有这些:SC0067、SC0070、10TP583T、OTP系列(如OTP-537F2、OTP- ...…

查看全部问答>

关于硬盘无刷电机的驱动

小弟在研究硬盘电机的驱动,我曾试过用小功率管9013,8050,8550等等来搭成达林顿管子,但是驱动电机的时候发热严重,而且明显有气无力...虽然能转...在网上找了很久,想用场效管IRF540N来驱动,但是不知道电路如何搭建...求各位高手,走过路过的能 ...…

查看全部问答>

针对beaglebone 扩展板,进行Linux驱动的调试!

好久没有发帖子了!今天来分享一下针对beaglebone 扩展板,进行Linux驱动的调试吧! 第二次修正beaglebone板子的外围电路还是比较顺利的! 具体编译内核的过程就不在介绍了!论坛里有很多人写了这方面的教程,Ti官方的文档也提供了较为全面的编译 ...…

查看全部问答>

J_smiason教你走进quartus,全程设计FPGA

都到这个点了,真的好瞌睡啊,希望这个文档能对初学的人带来帮助 我也是磕磕绊绊好几周才弄懂了整个开发的流程,希望初学的人来看 看我这篇文档,在开发中少走弯路,不走弯路 我是西安电子科技大学测控技术与仪器专业的学生,欢迎交流,共同进步 ...…

查看全部问答>

晒设计方案+MDK5.0下新建STM32F429i工程步步入门

晒设计方案+MDK5.0下新建STM32F429i工程步步入门 环境说明:1 Keil uVision52 STM32F429I-Discovery_FW_V1.0.1 一 工作目录路径1 在STM32F429I-Discovery_FW_V1.0.1目录下新建自己的总工程文件夹”My_Projects”. 2 为第一个工程试验新建文件夹 ...…

查看全部问答>