找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3004|回复: 1
打印 上一主题 下一主题
收起左侧

再来一个原创单片机按键状态机程序:单击双击长按(带抬起检测)

[复制链接]
跳转到指定楼层
楼主
ID:130230 发表于 2019-12-27 15:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//头文件(.h)
#ifndef  __KEY__
#define  __KEY__

#define DEBUG_KEY //key文件的调试开关

sbit KEY1 = P1^0;
#define KEY_DOWN             0
#define KEY_UP         1

//按键值
typedef enum
{
        NONE_CLICK = 0,
        SINGLE_CLICK ,
        DOUBLE_CLICK,
        LONG_PRESS,
        NUM_KEY,
}KEY_VALUE_EN;

typedef enum
{
        KEY_IDLE = 0,
        KEY_FILTER,
        KEY_FIRST,                //第一次按下
        KEY_CHECK_FREE,//抬起检测(长按)
        NUM_KEY_STAUS,
}KEY_STATUS_EN;


//按键扫描状态
typedef struct
{
        unsigned char Statu;
        unsigned char CntDly;
        unsigned char KeyValue;

}TASK_KEY_STATU_ST;
void Task_Keyscan(void);
void Switch_KeyState(unsigned char state);

#endif

//.C文件
/****************************************
版权:微信:mcu6666
PS:承接单片机开发项目
*****************************************/
#include "..\Public\CH554.H"                                                         
#include "..\Public\Debug.H"
#include "key.h"
#include "UART1.H"

TASK_KEY_STATU_ST gstKey1 = {0};


/***********************************************
功能:按键扫描
作者:jzb2019年12月27日
备注:50ms运行一次这个函数,理论上可以扩展到n连击
        最大响应延时500ms(单击时)
***********************************************/
void Task_Keyscan(void)
{
        switch (gstKey1.Statu)
                {
                        case KEY_IDLE:
                                {
                                        if(KEY1 == KEY_DOWN)
                                                {
                                                        Switch_KeyState(KEY_FILTER);//按键按下了去抖
                                                }
                                }
                        break;
                        case KEY_FILTER:
                                {
                                        if(KEY1 == KEY_DOWN)
                                                {
                                                        gstKey1.CntDly++;
                                                        if(gstKey1.CntDly >= 60)
                                                                {
                                                                        gstKey1.KeyValue = LONG_PRESS;//长按
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("LONG_PRESS\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起检测
                                                                }
                                                }
                                        else
                                                {
                                                        if(gstKey1.CntDly == 0)
                                                                {
                                                                        Switch_KeyState(KEY_IDLE);//如果没有计数则证明是毛刺滤掉
                                                                }
                                                        else
                                                                {
                                                                        Switch_KeyState(KEY_FIRST);//转到第一次按下状态
                                                                }
                                                }
                                }
                        break;
                        case KEY_FIRST:
                                {
                                        if(KEY1 == KEY_UP)//释放了
                                                {        
                                                        gstKey1.CntDly++;
                                                        if(gstKey1.CntDly > 10)//500ms
                                                                {
                                                                        gstKey1.KeyValue = SINGLE_CLICK;
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("SINGLE\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_IDLE);//回到空闲
                                                                }
                                                }
                                        else//按下了
                                                {
                                                        if(gstKey1.CntDly == 0)//没有计数证明是没有释放按键的动作
                                                                {

                                                                }
                                                        else//这个分支里面已经是第二次按下了
                                                                {
                                                                        gstKey1.KeyValue = DOUBLE_CLICK;
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("DOUBLE\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起检测
                                                                }
                                                }
                                }
                        break;
                        case KEY_CHECK_FREE:
                                {
                                        if(KEY1 == KEY_UP)
                                                {        
                                                        Switch_KeyState(KEY_IDLE);
                                                }
                                }
                        break;
                    default :
                                  {
                                        Switch_KeyState(KEY_IDLE);
                                  }
                        break;        
                }
}

/****************************************************************************
功能:执行切换状态的动作,同时清掉当前状态内的计数
入口:要切换的状态
作者:jzb 2019年12月27日
备注:暂时先不考虑通用的问题,直接操作全局变量如果扩展按键再说
*****************************************************************************/
void Switch_KeyState(unsigned char state)
{
        gstKey1.CntDly = 0;
        gstKey1.Statu = state;
}

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:984376 发表于 2024-4-26 21:34 | 只看该作者
Debug.H没放出来
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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