找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 455|回复: 2
收起左侧

半阻塞式按键判断程序

[复制链接]
ID:18253 发表于 2026-2-23 22:35 | 显示全部楼层 |阅读模式
参考江协科技的定时器实现非阻塞式按键程序中对按键状态判断的思路,搞了一个半阻塞式按键判断程序,挺有意思。

#include <STC8H.H>
#include "delay.h"
#include "keyx3.h"


sbit k1 = P3^2;          
sbit k2 = P3^3;       
sbit k3 = P3^4;       

unsigned char num;

//==============================
unsigned char keynum()
{
        unsigned char temp;
        temp = num;
        num = 0;
        return temp;
}

unsigned char key_getnum()//输出与实际电平相反,有数值代表按下,0为未按下。
{
        if(k1 == 0)
        {
                return 1;
        }       

        if(k2 == 0)
        {
                return 2;
        }

        if(k3 == 0)
        {
                return 3;
        }

        return 0;
}


//--------------------------------------------
void key_tick()//在主函数轮循
{
        static unsigned char currstate, prevstate;

        delayms(20);//阻塞延时
        prevstate = currstate;           //当前状态传递到之前状态
        currstate = key_getnum();  //按键值传递到当前状态

        if(currstate != 0 && prevstate == 0)
        {
                num =  currstate;
        }

}
回复

使用道具 举报

ID:18253 发表于 2026-3-10 22:53 | 显示全部楼层
51单片机非阻塞多按键多功能程序,基于江科协教程修改。
#ifndef _KEYX3_H_
#define _KEYX3_H_


#define key_count  3

#define key1  0
#define key2  1
#define key3  2

#define hold       0x01//按住不放
#define down           0x02//按下时刻
#define up                   0x04//松开时刻
#define single           0x08//单击
#define ddouble           0x10//双击
#define llong           0x20//长按
#define repeat           0x40//重复


void key_tick();//放1ms中断定时器中
unsigned char key_check(unsigned char n, unsigned char flag);//n按键名,flag按键动作

#endif
回复

使用道具 举报

ID:18253 发表于 2026-3-10 22:56 | 显示全部楼层
基于江科协非阻塞按键教程修改,用于STC单片机环境多按键多功能按键程序
#ifndef _KEYX3_H_
#define _KEYX3_H_


#define key_count  3

#define key1  0
#define key2  1
#define key3  2

#define hold       0x01//按住不放
#define down           0x02//按下时刻
#define up                   0x04//松开时刻
#define single           0x08//单击
#define ddouble           0x10//双击
#define llong           0x20//长按
#define repeat           0x40//重复


void key_tick();//放1ms中断定时器中
unsigned char key_check(unsigned char n, unsigned char flag);//n按键名,flag按键动作

#endif
//=======================================================

#include <STC8H.H>
#include "keyx3.h"

#define pressed    1
#define unpressed  0

#define time_double  200
#define time_long    2000
#define time_reper   100

sbit k1 = P3^2;          
sbit k2 = P3^3;       
sbit k3 = P3^4;       
sbit led7 = P2^7;


                                                                      //7     6     5     4       3        2      1      0
unsigned char key_flag[key_count];        //空  repeat  long  double  single   up     down   hold
                                                                      //          0x40    0x20  0x10    0x08     0x04   0x02   0x01
//===========================================================

unsigned char key_getstate(unsigned char n)
{
        if(n == key1)
        {
                if(k1 == 0)
                {
                        return pressed;
                }
        }

        else if(n == key2)
        {
                if(k2 == 0)
                {
                        return pressed;
                }
        }

        else if(n == key3)
        {
                if(k3 == 0)
                {
                        return pressed;
                }
        }

        return unpressed;
}

//-------------------------------------------------------------------------
unsigned char key_check(unsigned char n, unsigned char flag)//通过对这参数各位检查,得出结果
{
        if(key_flag[n] & flag)
        {
                if(flag != 0x01)
                {
                        key_flag[n] &= ~flag;
                }
                return 1;
        }
        return 0;

}


void key_tick()
{
        static unsigned char count, i;
        static unsigned char prevstate[key_count], currstate[key_count];
        static unsigned char s[key_count];
        static unsigned int  time[key_count];
       
        for(i = 0; i < key_count; i++)
        {
                if(time[i] > 0 )
                {
                        time[i]--;
                }
       
        }


        count++;
        if(count >= 20)
        {
                count = 0;
                led7 = ~led7;

               
                for(i = 0; i < key_count; i++)
                {
                        prevstate[i] = currstate[i];
                        currstate[i] = key_getstate(i);
               
                //--基础事件---------------------------------------
                //--按下与松开,电平触发-----------------------------               
                        if(prevstate[i] == pressed)
                        {
                                //hold = 1
                                key_flag[i] |= hold;
                        }
                        else
                        {
                                //hold = 0
                                key_flag[i] &= ~hold;
                        }
               
                //--松开后按下,下降沿触发------------------------------               
                        if(prevstate[i] == unpressed && currstate[i] == pressed)
                        {
                                //down = 1
                                key_flag[i] |= down;
                        }
               
                //--按下后松开,上升沿触发------------------------------
                        if(prevstate[i] == pressed && currstate[i] == unpressed)
                        {
                                //up = 1
                                key_flag[i] |= up;
                        }
               
               
                //--高级事件-----------------------------------------------
                        if(s[i] == 0)//空闲
                        {
                                if(currstate[i] == pressed)
                                {
                                        time[i] = time_long;//设定长按时间
                                        s[i] = 1;
                                }       
                        }
               
                        else if(s[i] == 1)//按键已按下
                        {
                                if(currstate[i] == unpressed)
                                {
                                         time[i] = time_double;//设定双击时间
                                        s[i] = 2;
                                }
                                else if(time[i] == 0)//长按时间到
                                {
                                        time[i] = time_reper;
                                        //llong = 1
                                        key_flag[i] |= llong;
                                        s[i] = 4;
                                }       
                        }
               
                        else if(s[i] == 2)//按键已松开
                        {
                                if(currstate[i] == pressed)
                                {
                                        //double = 1;
                                        key_flag[i] |= ddouble;
                                        s[i] = 3;
                                }
                                else if(time[i] == 0)//设定双击时间到
                                {
                                        //single = 1;
                                        key_flag[i] |= single;
                                        s[i] = 0;
                                }                       
                        }
               
                        else if(s[i] == 3)//按键已双击
                        {
                                if(currstate[i] == unpressed)
                                {
                                        s[i] = 0;
                                }       
                        }
               
                        else if(s[i] == 4)//按键已长按
                        {
                                if(currstate[i] == unpressed)
                                {
                                        s[i] = 0;
                                }
                                else if(time[i] == 0)//重复时间到
                                {
                                        time[i] = time_reper;
                                        //repeat = 1
                                        key_flag[i] |= repeat;
                                        s[i] = 4;
                                }
                                       
                        }
               
                }//for大括号

//------------------------------------------       
        }//20ms大括号
}//函数大括号

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表