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

发布者:MoonlightStar最新更新时间:2016-03-14 来源: eefocus关键字:独立按键  连续  步进触发 手机看文章 扫描二维码
随时随地手机看文章
开场白:

上一节讲了同一个按键短按与长按的区别触发功能,这节要教会大家两个知识点:

第一个知识点:如何在上一节的基础上,略作修改,就可以实现按住一个独立按键不松手的连续步进触发。

第二个知识点:在单片机的C语言编译器中,当无符号数据0减去1时,就会溢出,变成这个类型数据的最大值。比如是unsigned int类型的0减去1就等于65535(0xffff),unsigned char类型的0减去1就等于255(0xff)。这个常识经常要用在判断数据临界点的地方。比如一个数最大值是20,最小值是0。这个数据一直往下减,当我们发现它突然大于20的时候,就知道它溢出了,这个时候要及时把它赋值成0就达到我们的目的。

 

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

 

(1)硬件平台:基于朱兆祺51单片机学习板。用矩阵键盘中的S1和S5号键作为独立按键,记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。

 

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

 

 

(3)源代码讲解如下:

#include "REG52.H"

 

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

 

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

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

 

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

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

 

 

 

void initial_myself();    

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void T0_time();  //定时中断函数

void key_service(); //按键服务的应用程序

void key_scan(); //按键扫描函数 放在定时中断里

void led_run();  //led灯的应用程序

 

sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键

sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键

sbit key_gnd_dr=P0^4; //模拟独立按键的地GND,因此必须一直输出低电平

 

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

 

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

 

 

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

 

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

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

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

 

 

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

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

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

 

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

 

unsigned int  uiSetNumber=0; //设置的数据

 

void main() 

  {

   initial_myself();  

   delay_long(100);   

   initial_peripheral(); 

   while(1)  

   { 

       key_service(); //按键服务的应用程序

           led_run();  //led灯的应用程序

   }

 

}

 

void led_run()  //led灯的应用程序

{

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

   {

      led_dr=0;  //灭

   }

   else

   {

      led_dr=1;  //亮

   }

}

 

 

void key_scan()//按键扫描函数 放在定时中断里

{  

/* 注释一:

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

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

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

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

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

*         清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。这是我实战中摸索出来的。

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

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

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

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

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

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

*/

  if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位

  {

     ucKeyLock1=0; //按键自锁标志清零

     uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。    

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

  }

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

  {

     uiKeyTimeCnt1++; //累加定时中断次数

     if(uiKeyTimeCnt1>const_key_time1)

     {

        uiKeyTimeCnt1=0; 

        ucKeyLock1=1;  //自锁按键置位,避免一直触发

        ucKeySec=1;    //触发1号键

     }

  }

  else if(uiKeyTimeCnt1

  {

     uiKeyTimeCnt1++;

  }

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

  {

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

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

         {

             uiKeyCtntyCnt1=0; //

         ucKeySec=1;    //触发1号键

         }

   

  }

 

 

 

  if(key_sr2==1)

  {

     ucKeyLock2=0; 

     uiKeyTimeCnt2=0;

         uiKeyCtntyCnt2=0;

  }

  else if(ucKeyLock2==0)

  {

     uiKeyTimeCnt2++; //累加定时中断次数

     if(uiKeyTimeCnt2>const_key_time2)

     {

        uiKeyTimeCnt2=0;

        ucKeyLock2=1; 

        ucKeySec=2;     //触发2号键

     }

  }

  else if(uiKeyTimeCnt2

  {

      uiKeyTimeCnt2++;

  }

  else

  {

      uiKeyCtntyCnt2++;

          if(uiKeyCtntyCnt2>const_time_0_25s)

          {

             uiKeyCtntyCnt2=0;

                 ucKeySec=2;     //触发2号键

          }

  }

 

}

 

 

void key_service() //第三区 按键服务的应用程序

{

  switch(ucKeySec) //按键服务状态切换

  {

    case 1:// 1号键 连续加键  对应朱兆祺学习板的S1键  

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

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

                          {

                            uiSetNumber=20;

                          }

              uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。

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

          break;        

    case 2:// 2号键 连续减键  对应朱兆祺学习板的S5键

/* 注释二:

* 在单片机的C语言编译器中,当无符号数据0减去1时,就会溢出,变成这个类型数据的最大值。

* 比如是unsigned int的0减去1就等于65535(0xffff),unsigned char的0减去1就等于255(0xff)

*/

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

                          if(uiSetNumber>20) //最小是0.为什么这里用20?因为0减去1就是溢出变成了65535(0xffff)

                          {

                            uiSetNumber=0;

                          }

              uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。

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

          break;                    

  }                

}

 

 

 

void T0_time() interrupt 1

{

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

  TR0=0; //关中断

 

  key_scan(); //按键扫描函数

 

  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()  //第一区 初始化单片机

{

/* 注释三:

* 矩阵键盘也可以做独立按键,前提是把某一根公共输出线输出低电平,

* 模拟独立按键的触发地,本程序中,把key_gnd_dr输出低电平。

* 朱兆祺51学习板的S1和S5两个按键就是本程序中用到的两个独立按键。

*/

  key_gnd_dr=0; //模拟独立按键的地GND,因此必须一直输出低电平

 

 

  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;    //启动定时中断

 

}

总结陈词:

本程序可以有节奏地快速往上加或者快速往下减。假如被设置数据的范围不是20,而是1000。如果按0.25秒的节奏往上加,那不是累死人了?如果直接把0.25秒的节奏调快到0.01秒,那么到达999的时候,还来不及松手就很容易超过头,不好微调。有没有完整的方案解决这个问题?当然有。欲知详情,请听下回分解-----按住一个独立按键不松手的加速匀速触发。

关键字:独立按键  连续  步进触发 引用地址:第12节:按住一个独立按键不松手的连续步进触发

上一篇:第11节:同一个按键短按与长按的区别触发
下一篇:第13节:按住一个独立按键不松手的加速匀速触发

推荐阅读最新更新时间:2024-03-16 14:47

Counterpoint:中国手机市场销量连续降10周,仅荣耀保持增长
据 Counterpoint最新报告,与 2021 年同期相比,自 2022 年的第六周以来至今,中国市场智能手机销量已连续下降 10 周。 其表示,“动态清零”政策使消费者信心减弱,是智能手机销量下降的主要原因之一,目前可以很明显地看到,每一次疫情管控措施的收紧都关联着消费情绪。从1月底开始,北京冬奥会期间,随着隔离措施的逐步增强,智能手机销量开始同比下降。同样,在 3 月底,随着上海等主要城市开始实施管控措施,销售额进一步下降。然而,中国消费者信心在五一假期有所回升,因此预计智能手机销量会出现一些复苏。 Counterpoint认为,头部品牌均无法阻止和避免这种市场的整体收缩。除荣耀外,中国主要的智能手机品牌的销售额同比均
[手机便携]
Counterpoint:中国手机市场销量<font color='red'>连续</font>降10周,仅荣耀保持增长
2021上半年面板业续旺,有机会连续4季获利
台湾主要面板厂友达、群创、彩晶自今年第 3 季转亏为盈,专家表示,明年上半年面板供需平衡略偏紧,价格维持高档,今年第 4 季至明年上半年都有机会获利。因第 3 季面板价格上涨,带动面板厂转亏为盈。 全球经济预测及商业咨询机构 OMDIA 资深研究总监谢勤益表示,韩国面板厂已关闭约三分之二液晶面板产线,且面板上游零组件缺货,面板供不应求。谢勤益评估,面板大厂针对生产线在财务报表的「折旧摊提」已经完成,没有这方面的财务负担,所以照目前的电视面板售价来看,明年第 1 季不涨价也仍可赚钱,预期中国台湾主要面板厂自今年第 3 季转亏为盈之后,第 4 季可望接着获利,并持续到明年第 1 季,甚至第 2 季,连 4 季获利。 至于明年下
[嵌入式]
2021上半年面板业续旺,有机会<font color='red'>连续</font>4季获利
雷神动力连续十年蝉联“中国心”十佳发动机及混动系统
11月6日,经过专家评审委员会的严格测试审核,以44.26%超高热效率著称的新一代雷神电混引擎BHE15 Plus以及雷神电混8848混动系统,成功当选“中国心”2023年度十佳发动机及混动系统。 天津大学机械工程学院教授、博士生导师,“中国心”年度十佳发动机及混动系统评选专家评审委员会副主任姚春德表示,雷神电混8848系统将新一代雷神电混引擎BHE15 Plus、电动机与电池进行有机结合,通过动力高效化、驱动 电气化 、控制智能化和能源多样化,做到无里程焦虑,同时让用户感受到出色的动力性、经济性和安全性。 雷神动力已连续十年获得该荣誉,这是雷神动力聚焦创新研发、引领低碳发展的又一力证,彰显了雷神动力在混动领域的卓越
[汽车电子]
雷神动力<font color='red'>连续</font>十年蝉联“中国心”十佳发动机及混动系统
连续三年保持100%以上增速,稳石机器人完成Pre-A轮融资
9月4日,全场景物流机器人解决方案企业稳石机器人宣布完成Pre-A轮融资,由招商局集团旗下招商启航资本投资。 本次融资会延续稳石机器人既定战略重点的加强研发,投入到大规模多机器人协同系统研发和创新产品设计上 ,并通过提升机器人协同效率和逐步的量产化降低设备成本,提升作业效率,真正为制造业客户从根本上解决痛点。 稳石机器人核心团队研发和项目交付积累始于2015年,专注于自主移动机器人(AMR)全面自主研发及柔性物流解决方案交付 ,面向各垂直行业物流场景提供基于视觉融合导航的 AMR 机器人产品和综合柔性物流解决方案,是国内较早将激光SLAM、视觉SLAM技术融合并拥有大规模集群控制算法的企业之一。 在人才队伍上
[机器人]
Pure Storage连续8年蝉联Gartner“主存储魔力象限”领导者地位
Pure Storage连续8年蝉联Gartner“主存储魔力象限”领导者地位 并在Gartner“主存储关键能力”报告中的“容器”使用场景中拿下第一 2021年10月26日,中国——专为多云环境提供存储即服务的全球IT先锋Pure Storage宣布该公司在Gartner® “主存储魔力象限”(Magic Quadrant™ for Primary Storage)报告中再度荣登领导者象限。这是Pure Storage连续8年在Gartner魔力象限报告中获此殊荣,同时也是Pure连续2年在“远见完整性”与“执行能力”两大重要指标中双双拔得头筹。欲获取“Gartner 2021年主存储魔力象限”完整报告,请点击此链接。
[半导体设计/制造]
Pure Storage<font color='red'>连续</font>8年蝉联Gartner“主存储魔力象限”领导者地位
Checkmarx 连续第四年成为 2022 年 Gartner® Peer Insights™ 客户应用安全测试之选
客户发言:Checkmarx 连续第四年成为 2022 年 Gartner® Peer Insights™ 客户应用安全测试之选 Checkmarx 是唯一一家在所有三个细分市场组、北美和亚太部署区域以及中型企业公司规模中都被评为客户选择的供应商 中国北京, 2022年10月14日 - (ACN Newswire) – Checkmarx,以开发人员为中心的应用程序的全球领导者,连续四年在 Gartner® Peer Insights™ 上被客户认可为应用安全测试的客户之选。 自 2019 年 Peer Insights 客户选择类别首次亮相以来,Checkmarx 是唯一一家每年都获得此殊荣的供应商。这种认可是基于整体评
[汽车电子]
Checkmarx <font color='red'>连续</font>第四年成为 2022 年 Gartner® Peer Insights™ 客户应用安全测试之选
51单片机学习:独立按键实验
实验名称:独立按键实验 接线说明: 实验现象:下载程序后,按下“独立按键”模块中K1键,控制D1指示灯亮灭 注意事项: ***************************************************************************************/ #include reg52.h typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义独立按键控制脚 sbit KEY1=P3^1; sbit KEY2=P3^0; sbit KEY3=P3^2; sbit KEY4=P3^3; //定义LED
[单片机]
日本半导体设备订单额连续18个月同比下降
  据国外媒体报道,日本半导体设备协会(SEAJ)周四公布了8月份的初步统计数据,数据显示8月份日本半导体设备订单金额同比下降了47.7%。这已经是连续第18个月出现同比下降。   SEAJ称,由于内存芯片供应过剩,全球芯片生产商都削减了设备支出。按照订单金额计算,8 月日本半导体设备生产商拿到的订单只有723.9亿日元(约合6.93亿美元)。该机构还透露,8月份日本半导体设备生产企业的订单出货比(BB值)为 1.07,已经连续2个月订单金额超过销售收入。   这个比率意味着,6-8月每交付100日元的产品,就会收到价值107日元的新订单。SEAJ的数据显示,8月日本半导体设备生产商的销售收入为713.9亿日元,同比下降了59
[焦点新闻]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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