基于状态机的按键长按,短按,双击 单片机源程序

发布者:binggege最新更新时间:2020-02-09 来源: 51hei关键字:状态机  按键  单片机 手机看文章 扫描二维码
随时随地手机看文章

先前根据以为前辈的程序理解了一段时间,之后自己写了一份控制led灯的简单按键程序


单片机源程序如下:

#include

#include

#define key_state_0 0

#define key_state_1 1

#define key_state_2 2

#define key_state_3 3

#define key_no 0

#define key_click 1

#define key_double 2

#define key_long 3

sbit KEY = P3^3;

sbit LED_E1P = P3^1;

sbit LED_G1 = P3^2; 

sbit LED2 = P5^5;        //W2OUT

sbit LED3 = P5^4;  

unsigned char flag;

unsigned char cnt = 0;



static unsigned char key_driver(void)

{

        static unsigned char key_state_buffer1 = key_state_0;

        static unsigned char key_timer_cnt1 = 0;

        unsigned char key_return = key_no;

        unsigned char key;

        

        key = KEY;  //read the I/O states

        

        switch(key_state_buffer1)

        {

                case key_state_0:

                        if(key == 0)

                                key_state_buffer1 = key_state_1; 

                                //按键被按下,状态转换到按键消抖和确认状态//

                        break;

                case key_state_1:

                        if(key == 0)

                        {

                                key_timer_cnt1 = 0;

                                key_state_buffer1 = key_state_2;

                                //按键仍然处于按下状态

                                //消抖完成,key_timer开始准备计时

                                //状态切换到按下时间计时状态

                        }

                        else

                                key_state_buffer1 = key_state_0;

                                //按键已经抬起,回到按键初始状态

                        break;  //完成软件消抖

                case key_state_2:

                        if(key == 1) 

                        {

                                key_return = key_click;  //按键抬起,产生一次click操作

                                key_state_buffer1 = key_state_0;  //转换到按键初始状态

                        }

                        else if(++key_timer_cnt1 >= 100)  //按键继续按下,计时超过1000ms

                        {

                                key_return = key_long;  //送回长按事件

                                key_state_buffer1 = key_state_3;  //转换到等待按键释放状态

                        }

                        break;

                case key_state_3:  //等待按键释放

                        if(key == 1)  //按键释放

                                key_state_buffer1 = key_state_0;  //切回按键初始状态

                        break;

        }

        return key_return;

}


unsigned char key_read(void)

{

        static unsigned char key_state_buffer2 = key_state_0;

        static unsigned char key_timer_cnt2 = 0;

        unsigned char key_return = key_no;

        unsigned char key;

        

        key = key_driver();

        

        switch(key_state_buffer2)

        {

                case key_state_0:

                        if(key == key_click)

                        {

                                key_timer_cnt2 = 0;  //第一次单击,不返回,到下个状态判断是否会出现双击

                                key_state_buffer2 = key_state_1;

                        }

                        else 

                                key_return = key;  //对于无键、长按,返回原事件

                        break;

                case key_state_1:

                        if(key == key_click)  //又一次单击,时间间隔小于500ms

                        {

                                key_return = key_double;  //返回双击事件,回到初始状态

                                key_state_buffer2 = key_state_0;

                        }

                        else if(++key_timer_cnt2 >= 50)

                        {   

                        //这里在下一次的按键来临之前,并且时间是小于500ms的时候,就会一直执行的是这个key_timer_cnt2++.直到下一次的按键到来,再判断看是双击还是单击。

                                //这里500ms内肯定读到的都是无键事件,因为长按大于1000ms

                                //在1s前底层返回的都是无键

                                                                        

                                key_return = key_click;  //500ms内没有再次出现单击事件,返回单击事件

                                key_state_buffer2 = key_state_0;  //返回初始状态

                                        

                        }

                        break;

        }

        

        return key_return;

}


void Timer0Init(void)                //1毫秒@11.0592MHz

{

        AUXR |= 0x80;                //定时器时钟1T模式

        TMOD &= 0xF0;                //设置定时器模式

        TL0 = 0xCD;                //设置定时初值

        TH0 = 0xD4;                //设置定时初值

        TF0 = 0;                //清除TF0标志

        TR0 = 1;                //定时器0开始计时

        ET0 = 1;


}

void IO_init()

{

    

    P3M0 = 0x01;

    P3M1 = 0x01;

    P5M0 = 0x00;

    P5M1 = 0x00;

    

}



void main(void)

{          

       unsigned char key = 1;

             Timer0Init();

           IO_init();

           LED_E1P = 1;

           LED_G1 = 1;

           LED2 = 1;

           LED3 = 0;

[1] [2]
关键字:状态机  按键  单片机 引用地址:基于状态机的按键长按,短按,双击 单片机源程序

上一篇:51单片机是如何产生串口中断的
下一篇:HX1838红外无线遥控模块51单片机程序

推荐阅读最新更新时间:2024-11-11 22:14

PWM的单片机产生
在上次说的直流电机调速的项目中,用了S52单片机的T2定时器产生PWM波信号,用于控制直流电机的转速,虽然电机的平均速度与占空比不是严格的线性关系,但是在调节占空比可以明显的看出电机转速发生了改变,也算是满足了课题的要求。下面复习一下PWM的知识吧。 PWM 脉冲宽度调制(Pulse Width Modulation),是一种周期一定而高低电平可调的方波信号。当输出脉冲的频率一定时,输出脉冲的占空比越大,相对应的输出有效电压越大。PWM可以应用在许多方面,如电机调速、温度控制、压力控制等。 图1 PWM波示意图 如上图所示T1为脉冲宽度(就是导通时间),周期为T,则输出电压的平均值为U=VCC*T1
[单片机]
PWM的<font color='red'>单片机</font>产生
ST推出新款超低功耗STM32微控制器
同级最高的闪存容量,最大容量高达512KB。 中国,2014年3月26日 ——意法半导体STM32 L1系列超低功耗ARM® Cortex®-M3 32位微控制器新增一款512KB闪存产品。目前L1系列共有三个产品线合70余款产品,其超低功耗和存储容量的组合在市场上堪称独一无二,闪存和RAM最大容量分别高达512KB和80KB。 新产品采用意法半导体独有的超低泄漏电流的110纳米CMOS制造工艺和优化的系统架构,工作能耗极低,目标应用瞄准高成本效益的嵌入式设计,适用于健身、医疗、穿戴式设备和工业/电表等电池供电的联网产品。 L1系列的主要特性: · 高性能ARM Cortex-M3 32位内核:在32
[单片机]
ST推出新款超低功耗STM32<font color='red'>微控制器</font>
简单计时器的51单片机实现
前言 闲来无聊,虽然期末考试临近,但还是不想复习。突然有朋友问我这个 用单片机控制两个LED数码,采用静态链接,要求两个数码管显示00~99计数,时间间隔为1s(中断方式)。分别设计出电路图和程序。 我一寻思,这个简单,我就直接源代码一敲就发给他了。事后还是觉得有必要验证一下,就在Protues里面仿真试了一下,果然有两个小细节错了
[单片机]
简单计时器的51<font color='red'>单片机</font>实现
51单片机串口使用方法与设计实验
很多朋友在使用单片机串口的时候存在着一定的问题,我根据自己的经验,给大家总结如下: 串口调试 经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。 程序如下: //这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收 //和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的 #i nclude reg51.h #i nclude stdio.h #i nclude string.h #define INBUF_LEN 4 //数据长度 unsigned char inbuf1 ; unsigned char checksum,count3 , flag,temp,ch
[单片机]
飞思卡尔16位单片机(一)——飞思卡尔单片机简介
单片机是一种集成电路芯片,是微型计算机的一个分支,采用超大规模集成电路技术将计算机的CPU、存储器、输入输出设备集成在一块芯片上。通常用字母MCU(Microcontroller Unit)来表示单片机。从1971年Intel首次宣布其4位微处理器4004至今,单片机已有40年的历史,随着单片机位数由8位、16位直至32位的发展,单片机的功能、性能、速度和存储器容量等也在飞速发展。 飞思卡尔单片机产品的技术最早起源于1974年的8位处理器MC6800和后来的MC6801。其使用HCMOS工艺,功耗高。世界上最早出现的CMOS单片机是MC146805,后来出现了高速CMOS工艺的MC68HC05单片机,产量突破了2
[单片机]
单片机交通灯C语言程序
这是一款单片机交通灯C语言程序,单片机用的是AT89C51,两只共阴两位一体的数码管分另显示两个路口的倒计时,用12只发光二极管模拟红、黄、绿灯。电路简单,制作容易。 电子小制作 。 #include reg51.h #define uchar unsigned char bit flag; sbit red1_1=P1^0; //南北红灯D1 sbit yel1_1=P1^1; //南北黄灯D2 sbit gre1_1=P1^2; //南北绿灯D3 sbit red1_2=P1^3; //南北红灯D4 sbit yel1_2=P1^4; //南北黄灯D5 sbit gre1_2=P1^5; //南北
[单片机]
三星Note10取消全部手机实体按键
除了三星Galaxy Fold,三星另外一款旗舰产品——三星Note10也渐渐浮出水面,作为三星下半年的旗舰产品之一,自然同样极受粉丝和消费者关注。5月21日,三星Note10的核心配置又有了进一步消息,比如三星很有可能取消了这款手机的所有实体按键,改用全触控操作方式。 三星Note10正面搭载19:9的6.66英寸屏幕,但是机身尺寸可能与搭载6.4英寸屏幕的三星Note9相似,这不仅意味着其可以保持优秀的握持感,还将进一步提升屏占比;搭载高通骁龙855移动平台,但是在美国、印度等地区发售的版本将使用三星Exynos 9820处理器;内置4300mAh电池,高配版本则为4500mAh。在拍照上,后置四摄,而且很有可能使用
[手机便携]
英飞凌推出全新高性能微控制器AURIX™ TC4Dx
11月6日,英飞凌科技股份公司(Infineon Technologies AG)宣布推出AURIX™ TC4Dx微控制器(MCU),这是最新AURIX TC4x系列的首款产品。基于28nm技术的AURIX TC4Dx可提供更高的性能和高速连接。 图片来源:英飞凌 该产品将功率和性能增强与虚拟化、人工智能、功能安全、网络安全和网络功能的最新趋势相结合,为新的电子/电气(E/E)架构以及下一代软件定义汽车铺平了道路。像AURIX TC4Dx这样的MCU对于控制和监控汽车中的各种系统至关重要,例如车辆运动控制、高级驾驶辅助系统(ADAS)和底盘。 英飞凌微控制器高级副总裁Thomas Boehm表示:“像我们新款AURI
[汽车电子]
英飞凌推出全新高性能<font color='red'>微控制器</font>AURIX™ TC4Dx
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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