zoukankan      html  css  js  c++  java
  • 单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机

      前端时间要用按键,搞了个状态机(如图):

     main.c

     1 #include <N76E003.H>
     2 #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
     3 #include <Function_define.h>            //功能定义
     4 #include "data.h"
     5 #include "interrupt.h"
     6 #include "button.h"
     7 /*--------------------------------------------------------*/
     8 // 初始化所有
     9 void Init_All(void){
    10     InitMcu();                // 初始化MCU
    11     Init_button();            // 键盘初始化
    12 }
    13 /*******************************************************************/
    14 // 发布版本
    15 void main(void){
    16     Init_All();
    17     while(1){
    18         ;
    19     }
    20 }

    data.h

     1 /*--------------------------------------------------------------------------
     2 data.h
     3 --------------------------------------------------------------------------*/
     4 #ifndef __DATA_H__
     5 #define __DATA_H__
     6 
     7 
     8 /*----------------------------------------------------*/
     9 // 按键状态(状态定义)
    10 #define  Button_DOWN                0        // 按键按下
    11 #define  Button_UP                    1        // 按键抬起
    12 // 按键功能模式(软件模式定义)
    13 #define  Button_mode_NoOperation        0        // 无动作
    14 #define  Button_mode_ShortPress            1        // 短按
    15 #define  Button_mode_longPress            2        // 长按
    16 #define  Button_mode_evenPress            3        // 连续快按(双击)
    17 // 键盘消抖时间
    18 #define Button_TimeDebounce                20/2    // 单位 ms 去抖动时间
    19 #define Button_TimeShort_even            100/2    // 单位 ms 短按转连续按时间
    20 #define Button_TimeEvenPressinterval    5000/2    // 单位 ms 双击判断阈值
    21 #define Button_TimeState_reset            60000/2    // 单位 ms 60s 无动作 退出设置
    22 // 键盘状态机模式
    23 #define  Button_status_S0                0        // 等待按键按下
    24 #define  Button_status_S1                1        // 去抖验证
    25 #define  Button_status_S2                2        // 按下时间(计算是不是长按)
    26 #define  Button_status_S3                3        // 快安判断(判断是不是短按)
    27 #define  Button_status_S4                4        // 快安去抖
    28 #define  Button_status_S5                5        // 等待快安退出
    29 /*----------------------------------------------------*/
    30 #define Unit_cycle                    32000        // 中断处理周期
    31 /*----------------------------------------------------*/
    32 struct Button_data{
    33     unsigned int Button_LiftTime;                // 抬起时间
    34     unsigned int Button_PressTime;                // 按下时间
    35     unsigned char Button_State_machine_mode:3;    // 按键状态模式(状态机)
    36     unsigned char Button_statusmode:2;            // 0无动作 1短按 2连发 3长按
    37     unsigned char Button_status:1;                // 按键的状态(按键松开,界面刷新)
    38 
    39 };
    40 /*------------------------ 系统时间 ----------------------------*/
    41 struct OS_DATA{
    42     // 系统初始化
    43     unsigned char u8TH0_Tmp;                    // 中断高8位
    44     unsigned char u8TL0_Tmp;                    // 中断低8位
    45     // 键盘
    46     struct Button_data Button0;
    47 
    48 };
    49 
    50 extern struct OS_DATA DATA;
    51 #endif

    data.c

    1 #include "data.h" 
    2 
    3 struct OS_DATA DATA;            // 系统数据

    interrupt.h

     1 /*--------------------------------------------------------------------------
     2 interrupt.h
     3 --------------------------------------------------------------------------*/
     4 
     5 #ifndef __INTERRUPT_H__
     6 #define __INTERRUPT_H__
     7 
     8 /*----------------------------------------------------*/
     9 void InitMcu(void);
    10 #endif

    interrupt.c

     1 #include <N76E003.H>
     2 #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
     3 #include <Function_define.h>            //功能定义
     4 #include "data.h"
     5 #include "interrupt.h"
     6 #include "button.h"
     7 
     8 /*--------------------------------------------------------*/
     9 #define T0_INIT        Unit_cycle
    10 #define T0_ms         500
    11 /*--------------------------------------------------------*/
    12 //初始化单片机
    13 void InitMcu(void){
    14     TIMER0_MODE1_ENABLE;                         //定时器0的模式1
    15     set_T0M;                                    //设置定时器0的时钟为系统时钟
    16     //u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用
    17     //Init_OS_Date();已经初始化 
    18     DATA.u8TH0_Tmp = (65536-T0_INIT)/256;            //计算T0高8位数据
    19     DATA.u8TL0_Tmp = (65536-T0_INIT)%256;            //计算T0低8位数据
    20     TH0 = DATA.u8TH0_Tmp;                            //数据装入定时器0(计数器0)数据
    21     TL0 = DATA.u8TL0_Tmp;
    22     set_ET0;                                    //开启定时器0中断
    23     set_EA ;                                    //开启总中断
    24     set_TR0;                                    //启动定时器0
    25 }
    26 /**************************************************************************
    27 Function:    TIM1_UPD_OVF_IRQHandler
    28 Description: TIM1溢出中断 10ms
    29 Input:       no
    30 Output:      no
    31 Return:      no
    32 **************************************************************************/
    33 //定时器 ms
    34 void Timer0_ISR ( void ) interrupt 1  //interrupt address is 0x000B
    35 {
    36     //获取定时器数据
    37     TH0 = DATA.u8TH0_Tmp;
    38     TL0 = DATA.u8TL0_Tmp;
    39     // 按键时间模块
    40     All_Buttonrefresh();
    41 }
    42 /******************************************************************/

    button.h

     1 /*---------------------------------------------------------
     2     button.h
     3     按键控制
     4 ---------------------------------------------------------*/
     5 #ifndef _BUTTON_H_
     6 #define _BUTTON_H_
     7 /*----------------------------------------  数据初始化  ------------------------------------------*/
     8 #define button0_Num 5
     9 sbit button0 = P1^button0_Num;        // 按键
    10 #define Git_button0 button0
    11 /*----------------------------------------  数据获取部分  ------------------------------------------*/
    12 
    13 /*----------------------------------------  键盘初始化  ------------------------------------------*/
    14 void Init_button(void);
    15 void All_Buttonrefresh(void);
    16 
    17 #endif

    button.c

      1 #include <N76E003.H>
      2 #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
      3 #include <Function_define.h>            //功能定义
      4 #include "button.h"
      5 #include "data.h"
      6 
      7 /*----------------------------------------  数据宏定义  ------------------------------------------*/
      8 
      9 /*----------------------------------------  按键初始化  ------------------------------------------*/
     10 // 初始化按键
     11 void Init_button(void){
     12     //button1
     13     P1M1 |= (0x00 << button0_Num);        // 设置为1
     14     P1M2 &= ~(0x01 << button0_Num);        // 设置为0
     15 }
     16 /*----------------------------------------  功能模块  ------------------------------------------*/
     17 // 获取按键
     18 void Button_Process(struct Button_data* Button,bit status){
     19     switch(Button->Button_State_machine_mode){
     20         case Button_status_S0:{        // 等待按键按下
     21             if(Button_UP == status){        
     22                 Button->Button_status = Button_UP;        // 按键状态抬起
     23                 Button->Button_State_machine_mode = Button_status_S0;        // 无操作
     24                 Button->Button_statusmode = Button_mode_NoOperation;        // 按键无动作
     25                 DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + 1;    // 低状态计数
     26             }
     27             else if(Button_DOWN == status){            // 按键按下
     28                 Button->Button_State_machine_mode = Button_status_S1;    // 切换去抖模块    
     29                 Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
     30             }
     31         }break;
     32         case Button_status_S1:{        // 去抖验证
     33             if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
     34             else if(0 == Button->Button_PressTime){        // 去抖时间到
     35                 if(Button_UP == status){
     36                     Button->Button_State_machine_mode = Button_status_S0;        // 无操作
     37                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
     38                 }
     39                 else if(Button_DOWN == status){            // 短按成立
     40                     Button->Button_status = Button_DOWN;                    // 按键按下
     41                     Button->Button_State_machine_mode = Button_status_S2;    // 切换等待按键松开
     42                     Button->Button_PressTime = 0;            // 清零按下时间
     43                 }
     44             }
     45         }break;
     46         case Button_status_S2:{        // 按下时间(计算是不是长按)
     47             if(Button_DOWN == status){        // 按键按下
     48                 // 计时
     49                 Button->Button_PressTime = Button->Button_PressTime + 1;    // 按键计时
     50                 if(Button->Button_PressTime > Button_TimeEvenPressinterval){
     51                     Button->Button_PressTime = Button_TimeEvenPressinterval;
     52                 }
     53             }
     54             else if (Button_UP == status){        // 按键松开
     55                 if(Button->Button_PressTime == Button_TimeEvenPressinterval){
     56                     Button->Button_status = Button_UP;
     57                     Button->Button_State_machine_mode = Button_status_S0;
     58                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
     59                     Button->Button_statusmode = Button_mode_longPress;        // 长按
     60                 }else{
     61                     Button->Button_State_machine_mode = Button_status_S3;        // 短按 或 双击
     62                 }
     63                 Button->Button_LiftTime = 0;        // 按键松开计时
     64             }
     65         }break;
     66         case Button_status_S3:{        // 快安判断(判断是不是短按)
     67             Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
     68             if(Button->Button_PressTime > Button_TimeShort_even){    // 大于快安值
     69                 Button->Button_status = Button_UP;
     70                 Button->Button_State_machine_mode = Button_status_S0;        // 短按
     71                 DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
     72                 Button->Button_statusmode = Button_mode_ShortPress;            // 短按
     73             }else{
     74                 if(Button_DOWN == status){    // 按键按下
     75                     Button->Button_State_machine_mode = Button_status_S4;   // 双击去抖
     76                     Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
     77                 }
     78             }
     79         }break;
     80         case Button_status_S4:{            // 双击去抖
     81             Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
     82             if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
     83             else if(0 == Button->Button_PressTime){        // 去抖时间到
     84                 if(Button_UP == status){        // 去抖失败
     85                     Button->Button_status = Button_UP;
     86                     Button->Button_State_machine_mode = Button_status_S0;        // 短按
     87                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
     88                     Button->Button_statusmode = Button_mode_ShortPress;        // 短按
     89                 }
     90                 else if(Button_DOWN == status){            // 双击成立
     91                     Button->Button_status = Button_DOWN;                    // 按键按下
     92                     Button->Button_State_machine_mode = Button_status_S5;    // 切换等待按键松开
     93                 }
     94             }    
     95         }break; 
     96         case Button_status_S5:{        // 等待快安退出
     97             if(Button_UP == status){
     98                 Button->Button_status = Button_UP;
     99                 Button->Button_State_machine_mode = Button_status_S0;        // 双击
    100                 DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
    101                 Button->Button_statusmode = Button_mode_evenPress;            // 双击
    102             }
    103         }break; 
    104         default:{
    105             Button->Button_State_machine_mode = Button_status_S0;
    106             DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
    107         }break;        // 有问题转等待按键    
    108     }
    109     // Button->Button_status = status;
    110 }
    111 /*---------------------------------------- 中断调用模块 ------------------------------------------*/
    112 // 批处理函数
    113 void All_Buttonrefresh(void){
    114     Button_Process(&DATA.Button0,(bit)Git_button0);
    115 }

     工程文件:51内核按键状态机.rar

  • 相关阅读:
    父级和 子集 controller 之间的通讯
    ui-router(三)controller与template
    ui-router详解(二)ngRoute工具区别
    关于MySql全文索引
    Yii提供的Htmler助手checkboxList可自定义Checkbox输出格式
    添加和删除索引以及如何给中间表添加两个主键
    设置数据库及表的默认字符集
    保存数据的时候报类型错误的原因和解决方案
    金融经济
    YII获取刚插入数据的id主键
  • 原文地址:https://www.cnblogs.com/jikexianfeng/p/11510859.html
Copyright © 2011-2022 走看看