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

二、编写程序

/********************************************************************************************************************
----    @Project:  Independent-KEY
----    @File: main.c
----    @Edit: ZHQ
----    @Version:  V1.0
----    @CreationTime: 20200508
----    @ModifiedTime: 20200508
----    @Description:  两个独立按键S1和S2,S1键作为加键。S2键做为减键。每按一次S1键则被设置参数uiSetNumber自加1。如果按住S1键不松手超过1秒钟,被设置参数uiSetNumber以不断变快的时间间隔往上自加1,这个称为加速触发的功能,直到到达极限值,则以固定的速度加1,这个过程叫匀速。S2作为减法按键,每触发一次,uiSetNumber就减1,其加速和匀速触发功能跟S1按键一样。当被设置参数uiSetNumber小于500的时候,LED灯灭;当大于或者等于500的时候,LED灯亮。需要注意的是:
----    第一步:每次按下去触发一次单击按键,如果按下去到松手的时间不超过1秒,则不会进入连续加速触发模式。
----    第二步:如果按下去不松手的时间超过1秒,则进入连续加速触发模式。按键触发节奏不断加快,蜂鸣器鸣叫的节奏也不断加快。直到它们都到达一个极限值,然后以此极限值间隔匀速触发。在刚开始加速的时候,按键触发与蜂鸣器触发的步骤是一致的,等它们任意一个达到极限值的时候,急促的声音跟按键的触发不一致,并不是蜂鸣器每叫一次,按键就触发一次。实际上加速到最后,按键触发的速度远远比蜂鸣器的触发速度快。
----    单片机: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_1s   800     /*1秒钟的时间需要的定时中断次数*/#define const_initial_set 480 /*连续触发模式的时候,按键刚开始的间隔触发时间*/
#define const_min_level 90  /*连续触发模式的时候,按键经过加速后,如果一旦发现小于这个值,则直接变到最后的间隔触发时间*/
#define const_sub_dt    30  /*按键的"加速度",相当于按键间隔时间每次的变化量*/#define    const_last_min_set 15   /*连续触发模式的时候,按键经过加速后,最后的间隔触发时间*/
#define const_syn_min_level 90  /*产生同步声音的最小阀值 这个时间必须要比蜂鸣器的时间略长一点。*/
/*——————变量函数定义及声明——————*/
/*定义按键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 int uiKeyCtntyCnt1 = 0; /*按键连续触发的间隔延时计数器*/unsigned int  uiSynCtntyCnt1 = 0;   /*产生按键同步声音的计数器*/
unsigned int  uiCtntyTimeSet1 = const_initial_set; /*按键每次触发的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned int  uiCtntySynSet1 = const_initial_set;/*同步声音的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned char ucCtntyFlag1 = 0;  /*是否处于连续加速触发模式的标志位*/unsigned int  uiKeyTimeCnt2 = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock2 = 0; /*按键触发后自锁的变量标志*/
unsigned int uiKeyCtntyCnt2 = 0; /*按键连续触发的间隔延时计数器*/unsigned int  uiSynCtntyCnt2 = 0;   /*产生按键同步声音的计数器*/
unsigned int  uiCtntyTimeSet2 = const_initial_set; /*按键每次触发的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned int  uiCtntySynSet2 = const_initial_set;/*同步声音的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned char ucCtntyFlag2 = 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)
{BUZZER = 1;LED = 0;  Init_T0();
}
/**
* @brief  扫描按键函数
* @param  无
* @retval 独立按键连续加速扫描的过程:
* 第一步:每次按下去触发一次单击按键,如果按下去到松手的时间不超过1秒,则不会进入连续加速触发模式。
* 第二步:如果按下去不松手的时间超过1秒,则进入连续加速触发模式。按键触发节奏不断加快,蜂鸣器鸣叫的节奏
*         也不断加快。直到它们都到达一个极限值,然后以此极限值间隔匀速触发。在刚开始加速的时候,按键触发与
*         蜂鸣器触发的步骤是一致的,等它们任意一个达到极限值的时候,急促的声音跟按键的触发不一致,并不是
*         蜂鸣器每叫一次,按键就触发一次。实际上加速到最后,按键触发的速度远远比蜂鸣器的触发速度快。
**/
void Key_Scan(void)
{/*扫描S1*/if(Key_S1 == 1)  /*如果按键没有被按下(高电平),将一些标志位及时清零*/{ucKeyLock1 = 0;/*自锁标志位清0*/uiKeyTimeCnt1 = 0;/*按键去抖动延时计数器清零*/uiKeyCtntyCnt1 = 0; /*按键连续加速的时间间隔延时计数器清零*/uiSynCtntyCnt1 = 0;    /*蜂鸣器连续加速的时间间隔延时计数器清零*/uiCtntyTimeSet1 = const_initial_set;    /*按键每次触发的时间间隔初始值,这数值不断变小,导致速度不断加快*/uiCtntySynSet1 = const_initial_set;   /*同步声音的时间间隔初始值,这数值不断变小,导致鸣叫的节奏不断加快*/}else if(ucKeyLock1 == 0)   /*如果有按键按下,且是第一次按下*/{uiKeyTimeCnt1 ++;if(uiKeyTimeCnt1 > const_key_time1)/*判定按下*/{uiKeyTimeCnt1 = 0;ucKeyLock1 = 1;ucCtntyFlag1 = 0;  /*连续加速触发模式标志位 0代表单击  1代表连续加速触发*/ucKeySec = 1;    /*触发S1*/}}else if(uiKeyTimeCnt1 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/{uiKeyTimeCnt1 ++;}else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/{uiKeyCtntyCnt1 ++;/*连续触发延时计数器累加*/if(uiKeyCtntyCnt1 > uiCtntyTimeSet1)/*按住没松手,每隔一段uiCtntyTimeSet1时间按键就触发一次,而且uiCtntyTimeSet1不断减小,速度就越来越快*/{if(uiCtntyTimeSet1 > const_min_level){/*uiCtntyTimeSet1不断减小,速度就越来越快*/uiCtntyTimeSet1 = uiCtntyTimeSet1 - const_sub_dt;}else{/*达到极限值,则稳定为固定值*/uiCtntyTimeSet1 = const_last_min_set;}uiKeyCtntyCnt1 = 0;ucCtntyFlag1 = 1;  /*进入连续加速触发模式*/ucKeySec = 1;    /*触发S1*/}uiSynCtntyCnt1 ++;   /*蜂鸣器连续触发延时计数器累加*/if(uiSynCtntyCnt1 > uiCtntySynSet1)    /*按住没松手,每隔一段uiCtntySynSet1时间蜂鸣器就触发一次,而且uiCtntySynSet1不断减小,鸣叫的节奏就越来越快*/{uiCtntySynSet1 = uiCtntySynSet1 - const_sub_dt;if(uiCtntySynSet1 < const_syn_min_level){uiCtntySynSet1 = const_syn_min_level;}uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/uiSynCtntyCnt1 = 0;}}/*扫描S2*/if(Key_S2 == 1) /*如果按键没有被按下(高电平),将一些标志位及时清零*/{ucKeyLock2 = 0;/*自锁标志位清0*/uiKeyTimeCnt2 = 0;/*按键去抖动延时计数器清零*/uiKeyCtntyCnt2 = 0; /*按键连续加速的时间间隔延时计数器清零*/uiSynCtntyCnt2 = 0;    /*蜂鸣器连续加速的时间间隔延时计数器清零*/uiCtntyTimeSet2 = const_initial_set;    /*按键每次触发的时间间隔初始值,这数值不断变小,导致速度不断加快*/uiCtntySynSet2 = const_initial_set;   /*同步声音的时间间隔初始值,这数值不断变小,导致鸣叫的节奏不断加快*/}else if(ucKeyLock2 == 0)   /*如果有按键按下,且是第一次按下*/{uiKeyTimeCnt2 ++;if(uiKeyTimeCnt2 > const_key_time2)/*判定按下*/{uiKeyTimeCnt2 = 0;ucKeyLock2 = 1;ucCtntyFlag2 = 0;  /*连续加速触发模式标志位 0代表单击  1代表连续加速触发*/ucKeySec = 2;    /*触发S2*/}}else if(uiKeyTimeCnt2 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/{uiKeyTimeCnt2 ++;}else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/{uiKeyCtntyCnt2 ++;/*连续触发延时计数器累加*/if(uiKeyCtntyCnt2 > uiCtntyTimeSet2)/*按住没松手,每隔一段uiCtntyTimeSet1时间按键就触发一次,而且uiCtntyTimeSet2不断减小,速度就越来越快*/{if(uiCtntyTimeSet2 > const_min_level){/*uiCtntyTimeSet1不断减小,速度就越来越快*/uiCtntyTimeSet2 = uiCtntyTimeSet2 - const_sub_dt;}else{/*达到极限值,则稳定为固定值*/uiCtntyTimeSet2 = const_last_min_set;}uiKeyCtntyCnt2 = 0;ucCtntyFlag2 = 1;  /*进入连续加速触发模式*/ucKeySec = 2;    /*触发S2*/}uiSynCtntyCnt2 ++;   /*蜂鸣器连续触发延时计数器累加*/if(uiSynCtntyCnt2 > uiCtntySynSet2)    /*按住没松手,每隔一段uiCtntySynSet2时间蜂鸣器就触发一次,而且uiCtntySynSet2不断减小,鸣叫的节奏就越来越快*/{uiCtntySynSet2 = uiCtntySynSet2 - const_sub_dt;if(uiCtntySynSet2 < const_syn_min_level){uiCtntySynSet2 = const_syn_min_level;}uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/uiSynCtntyCnt2 = 0;}}  }
/**
* @brief  按键服务函数
* @param  无
* @retval 根据扫描得到的值,进行数据处理
**/
void key_Service(void)
{switch(ucKeySec){case 1: /*S1,连续加*/uiSetNumber++;/*被设置的参数连续往上加*/if(uiSetNumber > 1000)/*最大1000*/{uiSetNumber = 1000;}if(ucCtntyFlag1 == 0) /*如果是在单击按键的情况下,则蜂鸣器鸣叫,否则蜂鸣器在按键扫描key_scan里鸣叫*/{uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/                     }ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;   case 2: /*S2,连续减*/uiSetNumber--;/*被设置的参数连续往下减*/if(uiSetNumber > 1000)/*最小0,0 - 1 = 0xff > 1000*/{uiSetNumber = 0;}            if(ucCtntyFlag2 == 0) /*如果是在单击按键的情况下,则蜂鸣器鸣叫,否则蜂鸣器在按键扫描key_scan里鸣叫*/{uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/                     }       ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;        }
}
/**
* @brief  LED函数
* @param  无
* @retval 控制LED亮灭
**/
void Led_Run(void)  /*led灯的应用程序*/
{if(uiSetNumber < 500)  /*如果被设置的参数uiSetNumber小于500,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<uiDelayLong;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();      }
}

注:编程过程中遇到个小插曲,有个“>”写成了“<”。这种问题编译器不会报错,但现象就是不对,很多这种小细节,往往能影响到大局。

三、仿真实现

单片机学习笔记————51单片机实现按住一个独立按键不松手的加速匀速触发相关推荐

  1. 第十二节:按住一个独立按键不松手的连续步进触发

    第十二节:按住一个独立按键不松手的连续步进触发. 开场白: 上一节讲了同一个按键短按与长按的区别触发功能,这节要教会大家两个知识点: 第一个知识点:如何在上一节的基础上,略作修改,就可以实现按住一个独 ...

  2. 单片机学习笔记————51单片机实现带数码管显示的象棋比赛专用计时器

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  3. 单片机学习笔记————51单片机实现数码管中的倒计时程序

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  4. 单片机学习笔记————51单片机实现用LED灯和按键来模拟工业自动化设备的运动控制

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  5. 单片机学习笔记————51单片机实现带数码管显示的加法简易计算器

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  6. 单片机学习笔记————51单片机实现在数码管中实现iphone4S开机密码锁的程序

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  7. 单片机学习笔记————51单片机实现主机的串口收发

    proteus虚拟串口的实现:https://mp.csdn.net/console/editor/html/107251649 一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 / ...

  8. 单片机学习笔记————51单片机实现矩阵键盘的组合按键触发

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  9. C51汇编语言寻址方式,单片机学习:51单片机寻址方式详解

    原标题:单片机学习:51单片机寻址方式详解 51单片机是对所有兼容Intel 8031指令系统的单片机的统称.该系列单片机的始祖是Intel 8031单片机,后来随着Flash rom 技术的发展,8 ...

最新文章

  1. LeetCode Find All Anagrams in a String
  2. 导数,微积分,牛顿运动学制作创意地图
  3. ACM Computing Surveys 2021:基于会话推荐系统的最新长文综述
  4. Sql Server 监控 Job 执行情况
  5. 单链表排序(冒泡排序)(C语言)
  6. pix2pix笔记(B站,更加清晰)
  7. Composite UI Application Block(CAB)
  8. OSChina 周五乱弹 —— 谁家做的饭好吃 问新垣吉衣
  9. word在试图打开文件时遇到错误,解决办法
  10. 壹沓科技签约全球快消品牌巨头保乐力加,为企业数智化升级注入新动能
  11. 7 自定义 Git - Pro Git
  12. pytorch学习(一)数据加载之前的预处理(UCSD数据集)
  13. SOCKET与 线程 完成聊天室 非阻塞
  14. mes系统故障_MES系统上线后可能会遇到的问题
  15. 如何用 AppCube,实现那个曾经因为火,而被“封杀”的项目 Working Time丨【玩转应用魔方】
  16. vue配置多代理服务接口地址
  17. 小孢子的神奇之旅-如何阅读MindSpore报错信息(2)
  18. Apipost 基于设计、开发、测试一体化协作接口管理平台
  19. Linux PCIe驱动框架分析(第二章)
  20. hexo提交搜索引擎(百度+谷歌)

热门文章

  1. Go微服务(一)——RPC详细入门
  2. 大创比赛app开发项目学习规划
  3. H.266/VVC帧间预测总结
  4. 堡垒之夜显示连接服务器失败,堡垒之夜国服进不去怎么办 连接启动器登录失败解决方法...
  5. Bugku-闪的好快 60
  6. Using typename的理解
  7. 15平方用多大空调 15平方用大一匹还是1.5匹
  8. c++ 模板 声明与实现分开编写(error LNK2001: unresolved external symbol...)
  9. java gc机制 优点_聊聊Java的GC机制
  10. 有趣的HTML实例(八) 一个很有趣的动态背景(css+js)