历史上的今天
返回首页

历史上的今天

今天是:2025年02月09日(星期日)

正在发生

2020年02月09日 | 基于状态机的按键长按,短按,双击 单片机源程序

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;

推荐阅读

史海拾趣

厦门法拉(faratronic)公司的发展小趣事

在追求商业成功的同时,FMI公司也积极履行社会责任,致力于环保和可持续发展。公司制定了一系列环保计划和程序,以确保在所有业务运营中保持环保意识。FMI的产品从设计到生产都遵循环保原则,采用环保材料和工艺,减少对环境的影响。此外,公司还积极参与行业内的环保活动,推动整个电子行业的绿色发展。这种负责任的企业形象为FMI赢得了社会的广泛赞誉和尊重。

Allen Avionics Inc公司的发展小趣事

在追求商业成功的同时,FMI公司也积极履行社会责任,致力于环保和可持续发展。公司制定了一系列环保计划和程序,以确保在所有业务运营中保持环保意识。FMI的产品从设计到生产都遵循环保原则,采用环保材料和工艺,减少对环境的影响。此外,公司还积极参与行业内的环保活动,推动整个电子行业的绿色发展。这种负责任的企业形象为FMI赢得了社会的广泛赞誉和尊重。

Centellax Inc公司的发展小趣事

Centellax Inc公司自成立以来,一直致力于电子通信技术的研发与创新。在成立初期,公司凭借其独特的测试测量技术,在光通信行业中崭露头角。随着技术的不断迭代和市场的扩大,Centellax逐渐积累了大量的专利和知识产权,为公司的长期发展奠定了坚实的基础。

在技术创新方面,Centellax不断投入研发资源,推出了一系列高性能的测试测量设备。这些设备不仅满足了客户对高速器件深入分析的需求,还提升了公司在行业内的竞争力。同时,Centellax还积极与高校、研究机构等合作,共同推动电子通信技术的进步。

Bud Industries公司的发展小趣事

为了确保产品质量和客户满意度,Centellax建立了完善的质量管理体系。公司从原材料采购、生产制造到产品销售等各个环节都严格把控质量,确保产品性能稳定可靠。

同时,Centellax还引入了国际先进的质量管理理念和方法,不断提升员工的质量意识和技能水平。通过持续改进和优化生产流程,降低生产成本,提高产品竞争力。此外,公司还建立了完善的售后服务体系,为客户提供及时、专业的技术支持和解决方案。

Diotec Electronics Corp公司的发展小趣事

随着产品的不断成熟和市场的认可,Diotec开始积极拓展国内外市场。公司加强与国际知名电子企业的合作,不断提升产品的品质和技术水平。同时,Diotec还注重品牌建设,通过一系列的市场推广活动,提高了品牌的知名度和美誉度。这些努力使Diotec的产品在电子行业中占据了重要的地位,成为众多客户的首选供应商。

Hmc Inc公司的发展小趣事

另一家名为“Innovative Memory Solutions”的公司,在2008年就开始布局HMC技术的研发。经过数年的潜心研究,该公司终于在2012年推出了首款商用HMC产品。这款产品的问世,不仅解决了传统DRAM带宽受限的问题,还显著降低了系统延迟。Innovative Memory Solutions通过积极的市场推广和与OEM厂商的合作,成功将HMC技术应用于高性能计算、数据中心等领域,实现了从研发到市场的成功跨越。

问答坊 | AI 解惑

Linux 2.6 内核的嵌入式系统应用

摘 要:在分析Linux2.6内核新特性的基础上,在S3C2410开发板上移植了2.6内核和新的文件系统,并成功地对H.264编解码多媒体系统提供了支持。 关键词:Linux 内核 嵌入式系统 S3C2410…

查看全部问答>

压力机电路

各位大哥,我电子  菜鸟一个,前几天刚置了个压力机,想搞个全自动的,电路上一窍不通,求助大家给画个简图。谢谢大家。附图: 简单介绍: 1、压力泵站一个(双向电磁阀,压力表有三根线,可控制高压自停,低压自升) 2、所配保护器一 ...…

查看全部问答>

2010网络通信大方向:802.11n、WiMAX、光接入

2010年网络通信产业的三大发展重点是:802.11n成为WLAN主流标准、WiMAX、光接入(由于IPTV服务的推动,EPON和GPON设备出货比重将提升)。 2010年随着中国电信和中国网通陆续推出许多新方案,并且得标厂商将部分订单交由台湾厂商生产(如WiFi ADSL路由 ...…

查看全部问答>

汽车底盘测功机控制

有没有兄弟做过汽车底盘测功机控制系统的?现在我也在做这个东西,但是不是很熟悉,进行扭矩加载的时候控制不是很好,容易过载或者不足。有什么好的方法,望不吝赐教。可以联系我redshiliu@126.com or 13227015519…

查看全部问答>

熟悉Linux,C/C++,嵌入式开发,有两年的工作经验,请问在北京能拿多少?

熟悉Linux,C/C++,嵌入式开发,有两年的工作经验,请问在北京能拿多少?…

查看全部问答>

IEEE802.11B协议标准

想花3个月时间仔细研究IEEE802.11B协议. 顺便在自己的Windows CE上写个IEEE802.11b驱动. 可是不知道哪里有非常完整的协议规格标准书? 如果有中文就就更好了.…

查看全部问答>

STM32核心板供电问题

兄弟我做了一个STM32F10XVB的核心小板,包含CPU、晶体、电容、复位,100个管脚用了4个2X13的接插件引出,有个疑问: 将5个VDD接到一块,使用一个脚引出供电?还是使用5个脚供电?5个脚存在回路问题吧?另外VSS呢,地的接法应该怎样? 我初步想 ...…

查看全部问答>

求书!!!!!!!!!!!

那位大侠有这两本书,现在需要,谢谢!《基于quartus II的fpga/cpld设计与实践》,陈忠平;《基于quartus II的fpga/cpld设计与应用》,赵艳华,wangjiangqiang333@163.com不胜感激!!谢谢:\'(…

查看全部问答>