存在问题

大家主循环里写扫描按键状态的时候,想必都发觉了一个问题:要么按钮会重复起作用(每一次循环都会触发一次),要么只能用中断解决。如果是控制流水灯流速加速减速吧,按着就不断加减速,倒也方便;但是如果是切换模式或者启停这类的话,重复响应会造成很大麻烦。

原因分析

最主要的原因有两个:一是主循环速度非常快,而按键来不及释放返回初始电平。二是由于按键的内部弹片抖动,造成按键返回时会出现高低电平的震荡。从而导致了按键的重复响应。
问题最大症结,在于没法检测到“按下”“松开”的事件,只能探测到某时刻是抬起还是松开。要探测“按下”“松开”怎么办呢?我们可以借助一个辅助变量(标志位)。先让它与按钮电平相同(刚开始没按下,就是高电平);当按钮电平变化,它还没有改变,两者就不相等,这时就可以触发按下或松开的事件(要视当时按钮电平而定)。这时再让它与按钮电平相同,就不会重复触发。按钮电平再变化时,按钮电平与辅助变量又会不等,又会触发事件。看图:

于是我们就可以写出这样的代码:(52单片机,keil开发环境)

/**单次按钮触发例程*P3.0和P3.1搭上按钮,P0搭上灯就能用*/#include "reg52.h"#define led P0sbit sOn        = P3 ^ 0;sbit sMode        = P3 ^ 1;unsigned charbOn      = 1,bMode  = 1,flag_on = 0,mode = 1;void delay(unsigned int t){unsigned int x,y;for(x = t;x;x--)for(y = 110;y;y--);}void ledControl(){switch(mode){case 1://滚动if(!led)led = 1;elseled <<= 1;break;case 2://闪动led = ~led;}}void onBtnOnClick(){//可选:重置而非记忆闪烁模式mode = 1;flag_on = !flag_on;led = 0;}void onBtnOnOffClick(){}void onBtnModeClick(){++mode;if(mode > 2)mode = 1;led = 0;}void onBtnModeOffClick(){}void main(){unsigned int tdelay = 100;led = 0;for( ; ; )//与while(1)等效,没什么特别含义{if(sOn != bOn){//如果按钮是按下的(低电平)就是按下事件,否则是松开事件if(sOn == 0)onBtnOnClick();elseonBtnOnOffClick();//更新bOn,避免重复触发bOn = sOn;}//模式改变同理if(bMode != sMode){if(sMode == 0)onBtnModeClick();elseonBtnModeOffClick();bMode = sMode;}if(flag_on)ledControl();delay(tdelay);}}

显然这样的方法还有不少缺点:要和亮灯一起丢在一个循环里面,代码分离度不好,还占用运算时间……总之就是没有中断好用。不过中断不够用的情况下(按钮狂魔),这个方法我个人认为还是不错的。

作者:2020级黄家伟

如何不用中断实现按一次按键启停/响应事件相关推荐

  1. 单片机按键启停c语言,ZigBee-CC2530单片机 - 按键控制跑马灯的启停

    ZigBee-CC2530单片机 - 按键控制跑马灯的启停 程序源码 #include "ioCC2530.h" //引用CC2530头文件 #define LED1 (P1_0) ...

  2. 不用中断实现嘀嗒计数器

    使用中断实现嘀嗒计数器 一般情况下,使用一个计数器设定为1ms来一次中断,在中断服务例程中将嘀嗒计数器加1. uint32_t tick_count = 0;void timer_isr(void) ...

  3. K_A08_009 基于 STM32等单片机驱动TB6612模块按键控制直流电机正反转加减速启停

    目录 一.资源说明 二.基本参数 1.参数 2.引脚说明 三.驱动说明 TB6612模块驱动说明 对应程序: ENA ENB输出PWM 四.部分代码说明 接线说明 1.STC89C52RC+TB661 ...

  4. K_A08_005 基于 STM32等单片机驱动XY-160D模块按键控制直流电机正反转加减速启停

    目录 一.资源说明 二.基本参数 四.部分代码说明 接线说明 1.STC89C52RC+XY-160D模块 2.STM32F103C8T6+XY-160D模块 五.基础知识学习与相关资料下载 六.视频 ...

  5. K_A08_001 基于 STM32等单片机驱动L298N模块按键控制直流电机启停正反转加减速

    目录 一.资源说明 二.基本参数 1.参数 2.引脚说明 三.驱动说明 L298N模块驱动时序 对应程序: ENA ENB输出PWM 四.部分代码说明 接线说明 1.STC89C52RC+L298N模 ...

  6. K_A08_004 基于 STM32等单片机驱动MX1919模块按键控制直流电机正反转加减速启停

    目录 一.资源说明 二.基本参数 1.参数 2.引脚说明 三.驱动说明 1.MX1919模块驱动时序 2.对应程序: 3.PWM信号 四.部分代码说明 接线说明 1.STC89C52RC+MX1919 ...

  7. linux下获取按键响应事件(转)

    1.问题  通过一个死循环将读取键盘对应的设备文件将触发键盘事件在屏幕上打印出来,按esc退出程序  代码是在unbuntu10.04编译执行通过的 2.input_event描述  在Linux内核 ...

  8. 【Proteus仿真】Arduino+uln2003驱动步进电机+单按键启保停正反转控制

    [Proteus仿真]Arduino+uln2003驱动步进电机+单按键启保停正反转控制 Proteus仿真 功能实现 采用外部中断来获取按键信息 程序代码 #define LED ( 13 )#de ...

  9. 【Proteus仿真】Arduino UNO+uln2003驱动步进电机+按键启保停正反转控制

    [Proteus仿真]Arduino UNO+uln2003驱动步进电机+按键启保停正反转控制 Proteus仿真演示 功能说明 正反转采用2和3 引脚外部中断,3和4引脚调节加减速. 示例程序代码 ...

最新文章

  1. Verilog_Day2
  2. 全球及中国电子材料行业前景展望与投资机会分析报告2021年版
  3. GCC 编译时优化某一个或几个函数或者不优化某一个或几个函数
  4. Qt编写自定义控件及插件的使用
  5. 不妨问问自己,学习C语言是为了什么?
  6. Javascript实现的倒计时时钟
  7. NAPI 技术在 Linux 网络驱动上的应用和完善
  8. C++ Web 编程 CGI公共网关接口(CGI):第一个 CGI 程序
  9. c语言json配置文件linux,Linux C 编程——使用json-c库读取json格式的配置文件
  10. 解密Google Deepmind AlphaGo围棋算法
  11. Mybatis-plus的查,增,删
  12. 别让学历限制你,你可能是AI领域的下一个巨星
  13. dbz-ui试用体验(connecting mysql...)
  14. 宠物医院称可给怀孕宠物剖腹产 医生一对一护理
  15. arm920t中断系统详解
  16. JavaCV音视频开发宝典:JavaCV使用gdigrab方式实现windows录屏(windows屏幕画面抓取/采集,可实现高帧率屏幕截屏、录屏功能)
  17. http/https服务器安全:嗅探漏洞url路径
  18. 关联任天堂账号与服务器断开,任天堂疑似遇安全漏洞 多名NS玩家表示账户异常登录!...
  19. 《过故人庄》古诗鉴赏
  20. ZLG_GUI配置与函数介绍

热门文章

  1. Springboot+Netty实现基于天翼物联网平台CTWing(AIOT)终端TCP协议(透传模式)-应用订阅端(北向应用)
  2. kaggle中如何导入自定义的模块
  3. 中毒后的反思,我再也受不了
  4. jailbreakme问题-原生1.1.2破解经验分享!
  5. 新型 RORγt 小分子反向激动剂 | MedChemExpress
  6. animator创建动画_为游戏创建动画的基础
  7. 微信小程序 封装post请求 header加token code码拦截
  8. Mac程序坞只显示正在运行的应用图标
  9. 东大22春《电工电子技术及应用》在线平时作业2百分资料
  10. such as的用法总结