导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    新唐 N76E003 按键 单击/双击/长按 demo程序

    其它全志芯片讨论区
    1
    1
    1058
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • tigger
      tigger LV 7 最后由 编辑

      #include "N76E003.h"
      #include "Common.h"
      #include "Delay.h"
      #include "SFR_Macro.h"
      #include "Function_define.h"
      
      
      #define TIMER1_INIT        (6663 * 2)
      
      UINT8 u8TH1_Tmp,u8TL1_Tmp;
      UINT8 time_10ms_ok;
      
      unsigned char key;
      
      #define IO_KEY_INPUT    P10    // 按键输入口
      #define IO_BEEP         P30
      
      #define N_key           0             //无键
      #define S_key           1             //单键
      #define D_key           2             //双键
      #define L_key           3             //长键
      
      #define key_state_0         0
      #define key_state_1         1
      #define key_state_2         2
      #define key_state_3         3
      
      unsigned char key_driver(void)
      {
          static unsigned char key_state = key_state_0, key_time = 0;
          unsigned char key_press, key_return = N_key;
      
          key_press = IO_KEY_INPUT;                    // 读按键I/O电平
      
          switch (key_state)
          {
            case key_state_0:                              // 按键初始态
              if (!key_press) 
                  key_state = key_state_1;      // 键被按下,状态转换到按键消抖和确认状态
              break;
            
            case key_state_1:                      // 按键消抖与确认态
              if (!key_press)
              {
                   key_time = 0;                   //  
                   key_state = key_state_2;   // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
              }
              else
                   key_state = key_state_0;   // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
              break;
            
            case key_state_2:
              if(key_press)
              {
                   key_return = S_key;        // 此时按键释放,说明是产生一次短操作,回送S_key
                   key_state = key_state_0;   // 转换到按键初始态
              }
              else if (++key_time >= 100)     // 继续按下,计时加10ms(10ms为本函数循环执行间隔)
              {
                   key_return = L_key;        // 按下时间>1000ms,此按键为长按操作,返回长键事件
                   key_state = key_state_3;   // 转换到等待按键释放状态
              }
              break;
      
            case key_state_3:                 // 等待按键释放状态,此状态只返回无按键事件
              if (key_press) 
                  key_state = key_state_0; //按键已释放,转换到按键初始态
              break;
          }
          return key_return;
      }
      
      /*=============
      中间层按键处理函数,调用低层函数一次,处理双击事件的判断,返回上层正确的无键、单键、双键、长键4个按键事件。
      本函数由上层循环调用,间隔10ms
      ===============*/
      
      unsigned char key_read(void)
      {
          static unsigned char key_m = key_state_0, key_time_1 = 0;
          unsigned char key_return = N_key,key_temp;
           
          key_temp = key_driver();
           
          switch(key_m)
          {
              case key_state_0:
                  if (key_temp == S_key )
                  {
                       key_time_1 = 0;               // 第1次单击,不返回,到下个状态判断后面是否出现双击
                       key_m = key_state_1;
                  }
                  else
                       key_return = key_temp;        // 对于无键、长键,返回原事件
                  break;
      
              case key_state_1:
                  if (key_temp == S_key)             // 又一次单击(间隔肯定<500ms)
                  {
                       key_return = D_key;           // 返回双击键事件,回初始状态
                       key_m = key_state_0;
                  }
                  else                                
                  {                                  // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键
                       if(++key_time_1 >= 50)
                       {
                            key_return = S_key;      // 500ms内没有再次出现单键事件,返回上一次的单键事件
                            key_m = key_state_0;     // 返回初始状态
                       }
                   }
                   break;
          }
          return key_return;
      }     
      
      /*
      下面,根据程序分析按键事件的反映时间:
      1。对于长键,按下超过1s马上响应,反映最快
      2。对于双键,第2次按键释放后马上得到反映。
      3。对于单键,释放后延时拖后500ms才能响应,反映最慢。这个与需要判断后面是否有双击操作有关,只能这样。实际应用中,可以调整两次单击间隔时间定义,比如为300ms,这样单击的响应回快一点,单按键操作人员需要加快按键的操作过程。如果产品是针对老年人的,这个时间不易太短,因为年纪大的人,反映和动作都比较慢。
      
         当然,上面两段可以合在一起。我这样做的目的,是为了可以方便的扩展为N击(当然,需要做修改)。可是最底层的就是最基本的操作处理短按和长按,不用改动的。至于双击,还是N击,在中间层处理。这就是程序设计中分层结构的优点。
      
      测试代码环境如下:  
      */
      void Timer1_ISR (void) interrupt 3  // timer1定时器10ms中断服务
      {
          TH1 = u8TH1_Tmp;
          TL1 = u8TL1_Tmp;   
      
          P06 = ~P06;                     //P0.3 toggle when interrupt
          
          time_10ms_ok = 1;
      }
      
      main(void)  
      {  
          Set_All_GPIO_Quasi_Mode;
      
          TIMER1_MODE1_ENABLE; //定时器1, 模式1, 16bit定时器, 定时器值满 0xFFFF -> 0x0000 产生中断。
      
          clr_T1M;    //T1M = 0,兼容传统 8051, TIMER1时钟 = Fsys/12 = 16M /12
          //set_T1M;  //T1M = 1,               TIMER1时钟 = Fsys    = 16M 
      
          u8TH1_Tmp = (65536 - TIMER1_INIT)/256;
          u8TL1_Tmp = (65536 - TIMER1_INIT)%256;
      
          TH1 = u8TH1_Tmp;
          TL1 = u8TL1_Tmp;
          
          set_ET1;                                    //enable Timer1 interrupt
          set_EA;                                     //enable interrupts
          set_TR1;                                    //Timer1 run
          
          while (1) 
          {  
              if (time_10ms_ok)            //每10ms执行一次,  
              {  
                   time_10ms_ok =0;  
                   key = key_read();       //《====== 10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常  
                   
                   if(key == S_key) //短按
                   {
                       IO_BEEP = 0;
                       Timer0_Delay1ms(10);
                       IO_BEEP = 1;
                   }
                   else if(key == D_key) //双击
                   {
                       IO_BEEP = 0;
                       Timer0_Delay1ms(50);
                       IO_BEEP = 1;
                   }
                   else if (key == L_key) //长按
                   {
                       IO_BEEP = 0;
                       Timer0_Delay1ms(150);
                       IO_BEEP = 1;
                   }
               }  
           }  
      }
      

      IMG_20210715_110218.jpg

      1 条回复 最后回复 回复 引用 分享 0
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策