打印
[KungFu8位 MCU]

基于 N76E003 的按键按键状态机

[复制链接]
1173|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
merry_zsp|  楼主 | 2019-10-31 09:43 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
  前端时间要用按键,搞了个状态机(如图):

使用特权

评论回复
沙发
merry_zsp|  楼主 | 2019-10-31 09:44 | 只看该作者
main.c
#include <N76E003.H>
#include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h"
/*--------------------------------------------------------*/
// 初始化所有
void Init_All(void){
    InitMcu();                // 初始化MCU
    Init_button();            // 键盘初始化
}
/*******************************************************************/
// 发布版本
void main(void){
    Init_All();
    while(1){
        ;
    }
}

使用特权

评论回复
板凳
merry_zsp|  楼主 | 2019-10-31 09:44 | 只看该作者
data.h
/*--------------------------------------------------------------------------
data.h
--------------------------------------------------------------------------*/
#ifndef __DATA_H__
#define __DATA_H__


/*----------------------------------------------------*/
// 按键状态(状态定义)
#define  Button_DOWN                0        // 按键按下
#define  Button_UP                    1        // 按键抬起
// 按键功能模式(软件模式定义)
#define  Button_mode_NoOperation        0        // 无动作
#define  Button_mode_ShortPress            1        // 短按
#define  Button_mode_longPress            2        // 长按
#define  Button_mode_evenPress            3        // 连续快按(双击)
// 键盘消抖时间
#define Button_TimeDebounce                20/2    // 单位 ms 去抖动时间
#define Button_TimeShort_even            100/2    // 单位 ms 短按转连续按时间
#define Button_TimeEvenPressinterval    5000/2    // 单位 ms 双击判断阈值
#define Button_TimeState_reset            60000/2    // 单位 ms 60s 无动作 退出设置
// 键盘状态机模式
#define  Button_status_S0                0        // 等待按键按下
#define  Button_status_S1                1        // 去抖验证
#define  Button_status_S2                2        // 按下时间(计算是不是长按)
#define  Button_status_S3                3        // 快安判断(判断是不是短按)
#define  Button_status_S4                4        // 快安去抖
#define  Button_status_S5                5        // 等待快安退出
/*----------------------------------------------------*/
#define Unit_cycle                    32000        // 中断处理周期
/*----------------------------------------------------*/
struct Button_data{
    unsigned int Button_LiftTime;                // 抬起时间
    unsigned int Button_PressTime;                // 按下时间
    unsigned char Button_State_machine_mode:3;    // 按键状态模式(状态机)
    unsigned char Button_statusmode:2;            // 0无动作 1短按 2连发 3长按
    unsigned char Button_status:1;                // 按键的状态(按键松开,界面刷新)

};
/*------------------------ 系统时间 ----------------------------*/
struct OS_DATA{
    // 系统初始化
    unsigned char u8TH0_Tmp;                    // 中断高8位
    unsigned char u8TL0_Tmp;                    // 中断低8位
    // 键盘
    struct Button_data Button0;

};

extern struct OS_DATA DATA;
#endif

使用特权

评论回复
地板
merry_zsp|  楼主 | 2019-10-31 09:45 | 只看该作者
data.c
1 #include "data.h" 
2
3 struct OS_DATA DATA;            // 系统数据

使用特权

评论回复
5
merry_zsp|  楼主 | 2019-10-31 09:45 | 只看该作者
interrupt.h
/*--------------------------------------------------------------------------
interrupt.h
--------------------------------------------------------------------------*/

#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__

/*----------------------------------------------------*/
void InitMcu(void);
#endif

使用特权

评论回复
6
merry_zsp|  楼主 | 2019-10-31 09:45 | 只看该作者
interrupt.c
#include <N76E003.H>
#include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h"

/*--------------------------------------------------------*/
#define T0_INIT        Unit_cycle
#define T0_ms         500
/*--------------------------------------------------------*/
//初始化单片机
void InitMcu(void){
    TIMER0_MODE1_ENABLE;                         //定时器0的模式1
    set_T0M;                                    //设置定时器0的时钟为系统时钟
    //u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用
    //Init_OS_Date();已经初始化
    DATA.u8TH0_Tmp = (65536-T0_INIT)/256;            //计算T0高8位数据
    DATA.u8TL0_Tmp = (65536-T0_INIT)%256;            //计算T0低8位数据
    TH0 = DATA.u8TH0_Tmp;                            //数据装入定时器0(计数器0)数据
    TL0 = DATA.u8TL0_Tmp;
    set_ET0;                                    //开启定时器0中断
    set_EA ;                                    //开启总中断
    set_TR0;                                    //启动定时器0
}
/**************************************************************************
Function:    TIM1_UPD_OVF_IRQHandler
Description: TIM1溢出中断 10ms
Input:       no
Output:      no
Return:      no
**************************************************************************/
//定时器 ms
void Timer0_ISR ( void ) interrupt 1  //interrupt address is 0x000B
{
    //获取定时器数据
    TH0 = DATA.u8TH0_Tmp;
    TL0 = DATA.u8TL0_Tmp;
    // 按键时间模块
    All_Buttonrefresh();
}
/******************************************************************/

使用特权

评论回复
7
merry_zsp|  楼主 | 2019-10-31 09:45 | 只看该作者
button.h
/*---------------------------------------------------------
    button.h
    按键控制
---------------------------------------------------------*/
#ifndef _BUTTON_H_
#define _BUTTON_H_
/*----------------------------------------  数据初始化  ------------------------------------------*/
#define button0_Num 5
sbit button0 = P1^button0_Num;        // 按键
#define Git_button0 button0
/*----------------------------------------  数据获取部分  ------------------------------------------*/

/*----------------------------------------  键盘初始化  ------------------------------------------*/
void Init_button(void);
void All_Buttonrefresh(void);

#endif

使用特权

评论回复
8
merry_zsp|  楼主 | 2019-10-31 09:46 | 只看该作者
button.c
#include <N76E003.H>
#include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "button.h"
#include "data.h"

/*----------------------------------------  数据宏定义  ------------------------------------------*/

/*----------------------------------------  按键初始化  ------------------------------------------*/
// 初始化按键
void Init_button(void){
    //button1
    P1M1 |= (0x00 << button0_Num);        // 设置为1
    P1M2 &= ~(0x01 << button0_Num);        // 设置为0
}
/*----------------------------------------  功能模块  ------------------------------------------*/
// 获取按键
void Button_Process(struct Button_data* Button,bit status){
    switch(Button->Button_State_machine_mode){
        case Button_status_S0:{        // 等待按键按下
            if(Button_UP == status){        
                Button->Button_status = Button_UP;        // 按键状态抬起
                Button->Button_State_machine_mode = Button_status_S0;        // 无操作
                Button->Button_statusmode = Button_mode_NoOperation;        // 按键无动作
                DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + 1;    // 低状态计数
            }
            else if(Button_DOWN == status){            // 按键按下
                Button->Button_State_machine_mode = Button_status_S1;    // 切换去抖模块   
                Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
            }
        }break;
        case Button_status_S1:{        // 去抖验证
            if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
            else if(0 == Button->Button_PressTime){        // 去抖时间到
                if(Button_UP == status){
                    Button->Button_State_machine_mode = Button_status_S0;        // 无操作
                    DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
                }
                else if(Button_DOWN == status){            // 短按成立
                    Button->Button_status = Button_DOWN;                    // 按键按下
                    Button->Button_State_machine_mode = Button_status_S2;    // 切换等待按键松开
                    Button->Button_PressTime = 0;            // 清零按下时间
                }
            }
        }break;
        case Button_status_S2:{        // 按下时间(计算是不是长按)
            if(Button_DOWN == status){        // 按键按下
                // 计时
                Button->Button_PressTime = Button->Button_PressTime + 1;    // 按键计时
                if(Button->Button_PressTime > Button_TimeEvenPressinterval){
                    Button->Button_PressTime = Button_TimeEvenPressinterval;
                }
            }
            else if (Button_UP == status){        // 按键松开
                if(Button->Button_PressTime == Button_TimeEvenPressinterval){
                    Button->Button_status = Button_UP;
                    Button->Button_State_machine_mode = Button_status_S0;
                    DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
                    Button->Button_statusmode = Button_mode_longPress;        // 长按
                }else{
                    Button->Button_State_machine_mode = Button_status_S3;        // 短按 或 双击
                }
                Button->Button_LiftTime = 0;        // 按键松开计时
            }
        }break;
        case Button_status_S3:{        // 快安判断(判断是不是短按)
            Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
            if(Button->Button_PressTime > Button_TimeShort_even){    // 大于快安值
                Button->Button_status = Button_UP;
                Button->Button_State_machine_mode = Button_status_S0;        // 短按
                DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
                Button->Button_statusmode = Button_mode_ShortPress;            // 短按
            }else{
                if(Button_DOWN == status){    // 按键按下
                    Button->Button_State_machine_mode = Button_status_S4;   // 双击去抖
                    Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
                }
            }
        }break;
        case Button_status_S4:{            // 双击去抖
            Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
            if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
            else if(0 == Button->Button_PressTime){        // 去抖时间到
                if(Button_UP == status){        // 去抖失败
                    Button->Button_status = Button_UP;
                    Button->Button_State_machine_mode = Button_status_S0;        // 短按
                    DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
                    Button->Button_statusmode = Button_mode_ShortPress;        // 短按
                }
                else if(Button_DOWN == status){            // 双击成立
                    Button->Button_status = Button_DOWN;                    // 按键按下
                    Button->Button_State_machine_mode = Button_status_S5;    // 切换等待按键松开
                }
            }   
        }break;
        case Button_status_S5:{        // 等待快安退出
            if(Button_UP == status){
                Button->Button_status = Button_UP;
                Button->Button_State_machine_mode = Button_status_S0;        // 双击
                DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
                Button->Button_statusmode = Button_mode_evenPress;            // 双击
            }
        }break;
        default:{
            Button->Button_State_machine_mode = Button_status_S0;
            DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
        }break;        // 有问题转等待按键   
    }
    // Button->Button_status = status;
}
/*---------------------------------------- 中断调用模块 ------------------------------------------*/
// 批处理函数
void All_Buttonrefresh(void){
    Button_Process(&DATA.Button0,(bit)Git_button0);
}

使用特权

评论回复
9
qcliu| | 2019-11-13 12:04 | 只看该作者
非常不错的资料

使用特权

评论回复
10
tfqi| | 2019-11-13 12:44 | 只看该作者
非常不错的资料

使用特权

评论回复
11
wiba| | 2019-11-13 12:53 | 只看该作者
非常不错的资料

使用特权

评论回复
12
zljiu| | 2019-11-13 13:02 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
13
rgjinxuan| | 2020-3-18 11:38 | 只看该作者

非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

695

帖子

2

粉丝