搜索
bottom↓
回复: 17

stm8s105K4 多按键,多功能 长短按键 区分 有限状态机

[复制链接]

出0入0汤圆

发表于 2011-12-27 13:55:23 | 显示全部楼层 |阅读模式
自己测试没有什么问题,求鉴定
这个按键要每20MS 调用一下,然后用


原程序如下

/********************************
用之前把IO设置为上拉输入后每20ms调用一次就行了
每次调用 Skcankeystep()后再测试什么按键

按键处理  

*****/


#ifndef _stm8_key
#define _stm8_key 1
#include "stm8s207r.h"
#define key1   0
#define key2   1
#define key3   2
#define key4   3
#define Keyport PB_IDR
#define Key1up    (Keyport&(1<<key1))
#define Key1down  !(Keyport&(1<<key1))
#define Key2up    (Keyport&(1<<key2))
#define Key2down  !(Keyport&(1<<key2))
#define Key3up    (Keyport&(1<<key3))
#define Key3down  !(Keyport&(1<<key3))
#define Key4up    (Keyport&(1<<key4))
#define Key4down  !(Keyport&(1<<key4))
#define Key_mode_scan  1
#define Key_mode_delay  2
#define Key_mode_valu  3
#define Key_mode_K4UP 4


#define GIC_Key_Valu_Key1down 1
#define GIC_Key_Valu_Key2down 2
#define GIC_Key_Valu_Key3down 3
#define GIC_Key_Valu_Key4down 4

#define GIC_Key_Valu_Key1up  5
#define GIC_Key_Valu_Key2up  6
#define GIC_Key_Valu_Key3up  7
#define GIC_Key_Valu_Key4_long_up  8

#define  GIC_Key_Valu_Key4_short_up  9
#define  GIC_Key_Longkey_Delaytiem  250  //0.02S*250 =5s
#define  GIC_Key_Step_time          300

#define  GIC_Nokey   0;
#define  GIC_Cleardelay_time 0;
unsigned long int   GLV_Key_Scan_time;

unsigned int GIV_Key_valu;
unsigned int GIV_Key_Mode_Step=Key_mode_scan;
unsigned int GIV_Key4_delaytime ;


void Skcankey(void)
{
if(Key4down)
{
  GIV_Key_valu=4;
}
if(Key3down)
{
  GIV_Key_valu=3;
}
if(Key2down)
{
  GIV_Key_valu=2;
}
if(Key1down)
{
  GIV_Key_valu=1;
}
if(Key1up&&Key2up&&Key3up&&Key4up)
{
{
  GIV_Key_valu=5;
}
}


}
/**
以下程序是为了测试有状态机测试写的
2011年12月25日21时34分39秒
ver 01


*/
void Skcankeystep (void)
{
  switch(GIV_Key_Mode_Step)
  {
          case Key_mode_scan:
        {
           if (Key4down||Key3down||Key2down||Key1down)
          {
            if(Key1down)
       {
                                                GIV_Key_valu=GIC_Key_Valu_Key1down;
        }
                                if(Key2down)
        {
           GIV_Key_valu=GIC_Key_Valu_Key2down;
        }
                                if(Key3down)
        {
            GIV_Key_valu=GIC_Key_Valu_Key3down;
         }
                                 if(Key4down)
         {
           GIV_Key_valu=GIC_Key_Valu_Key4down;
          }
                                        GIV_Key_Mode_Step=Key_mode_delay;
          }       
   
         else
    {
                  GIV_Key_valu=GIC_Nokey;//把上次的值清去 2011年12月26日09时24分37秒test
                }               
         
           break;
        }
                  case Key_mode_delay://
        {  
          if (Key4down||Key3down||Key2down||Key1down)
          {
            if(Key1down)
       {
                                                GIV_Key_valu=GIC_Key_Valu_Key1down;
                                                GIV_Key_Mode_Step=Key_mode_valu;
        }
                                if(Key2down)
        {
           GIV_Key_valu=GIC_Key_Valu_Key2down;
                                         GIV_Key_Mode_Step=Key_mode_valu;
        }
                                if(Key3down)
        {
            GIV_Key_valu=GIC_Key_Valu_Key3down;
                                                GIV_Key_Mode_Step=Key_mode_valu;
         }
                                 if(Key4down)
         {
           GIV_Key_valu=GIC_Key_Valu_Key4down;
                                         
                                         GIV_Key_Mode_Step=Key_mode_valu;
                                         GIV_Key4_delaytime=GIC_Cleardelay_time;
          }
                                       
                }
               
                 else
    { GIV_Key_valu=GIC_Nokey;
                  GIV_Key_Mode_Step=Key_mode_scan;//这个是防止按键太快时
                        //在状态2中一直等待
                }       
        break;
        }
                  case Key_mode_valu:
        {
          switch(GIV_Key_valu)
        {
          case GIC_Key_Valu_Key1down:
          {         if(Key1up)
        {
            GIV_Key_valu=GIC_Key_Valu_Key1up;
                                                GIV_Key_Mode_Step=Key_mode_scan;
         }
                                 break;
                }
                case GIC_Key_Valu_Key2down:
          {         if(Key2up)
        {
            GIV_Key_valu=GIC_Key_Valu_Key2up;
                                                GIV_Key_Mode_Step=Key_mode_scan;
         }
                                 break;
                }
                case GIC_Key_Valu_Key3down:
          {         if(Key3up)
        {
            GIV_Key_valu=GIC_Key_Valu_Key3up;
                                                GIV_Key_Mode_Step=Key_mode_scan;
         }
                                 break;
                }
                                case GIC_Key_Valu_Key4down:
          {          GIV_Key4_delaytime++;
                   if(Key4down&&(GIV_Key4_delaytime>GIC_Key_Longkey_Delaytiem))
        {
            
                                                GIV_Key_Mode_Step=Key_mode_K4UP;
                                                GIV_Key4_delaytime=GIC_Cleardelay_time;
         }
                                 if(Key4up&&(GIV_Key4_delaytime<GIC_Key_Longkey_Delaytiem))
                         {
                         GIV_Key_valu=GIC_Key_Valu_Key4_short_up;
                         GIV_Key_Mode_Step=Key_mode_scan;
                         GIV_Key4_delaytime=GIC_Cleardelay_time; //n2011年12月25日23时03分36秒 test ok
                         }
                               
                       
                                 break;
                }
          
        }
         
          break;
        }
         case Key_mode_K4UP:
{
  if(Key4up)
  {
     GIV_Key_valu=GIC_Key_Valu_Key4_long_up;
                 GIV_Key_Mode_Step=Key_mode_scan;
                 GIV_Key4_delaytime=GIC_Cleardelay_time;
  }
     break;
}
        }
}
/*
状态机测试程序  2011年12月26日09时04分54秒

*/

#endif

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2011-12-27 13:58:59 | 显示全部楼层
还有我自己在网络下找的资料 也为按键处理的
都是在状态机的基础上做的

点击此处下载 ourdev_708004JHV2RX.doc(文件大小:32K) (原文件名:多功能按键.doc)
点击此处下载 ourdev_708005PD3DPE.doc(文件大小:44K) (原文件名:新型按键程序.doc)

出0入0汤圆

发表于 2011-12-27 20:59:19 | 显示全部楼层
谢谢楼主分享哈!

出0入0汤圆

 楼主| 发表于 2012-2-6 08:26:24 | 显示全部楼层
突然想起我的这个有个BUG ,,,, 就是它在按下时会有一个值.. 如果单独用这个值没有问题,,但当用到按键按下,与抬起时,在一个功能中,,,就会有问题...


               这个我要更改下,,以前版本有BUG ..请注意..不过如果我把变量增加一个,,就是在按下时的值放到一个变量中
              
                抬起时再放入一个变量 ,,然后测试想用的按键,,就好了........今天试试 ...

出0入0汤圆

发表于 2012-2-6 09:12:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-6 22:58:20 | 显示全部楼层
这个匠人手记里也有比较详细的分析。呵呵

出0入0汤圆

发表于 2012-2-15 09:19:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-15 10:42:08 | 显示全部楼层
好方法

出0入0汤圆

发表于 2013-1-17 10:38:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-1-22 06:24:25 来自手机 | 显示全部楼层
mark。。。

出0入0汤圆

发表于 2013-1-22 09:54:16 | 显示全部楼层
楼主V5,,

出0入0汤圆

发表于 2013-7-23 14:42:56 | 显示全部楼层
牛啊,正需要你,加油!!!!!

出0入0汤圆

发表于 2013-7-23 16:19:26 | 显示全部楼层
这个如何呢?思路比较清晰!
#ifdef SARADC_KEY_ENABLE//Add by EimanFeng 2013-07-03
#define KEY_SCAN_CFG_1  KEY_NEXT,
#define KEY_SCAN_CFG_2  KEY_PREV,
#define KEY_SCAN_CFG_3  KEY_VOLUP,
#define KEY_SCAN_CFG_4  KEY_VOLDN,
#define KEY_SCAN_CFG_5  KEY_ENTER,
#define KEY_SCAN_CFG_6  
#define KEY_SCAN_CFG_7  
#define KEY_SCAN_CFG_8  
#define KEY_SCAN_CFG_9  
#define KEY_SCAN_CFG_10

UINT8 c_aKeyParam_Tab[] =
{
KEY_SCAN_CFG_1  KEY_SCAN_CFG_2  KEY_SCAN_CFG_3  KEY_SCAN_CFG_4  KEY_SCAN_CFG_5
KEY_SCAN_CFG_6  KEY_SCAN_CFG_7  KEY_SCAN_CFG_8  KEY_SCAN_CFG_9  KEY_SCAN_CFG_10
};

KEY_INFO g_KeyInfo = {KEY_NULL,KEY_EVENT_IDLE,0};
UINT16 g_uiKeyCode = MSG_BOX_NULL;

UINT8 Get_Max_Key(void)
{
return (sizeof(c_aKeyParam_Tab)/sizeof(UINT8));
}

void Key_Event(UINT8 m_ucKeyCode)
{
UINT8 m_ucKeyIndex;

switch(g_KeyInfo.Status)
{
  case KEY_EVENT_IDLE:
   if(m_ucKeyCode == KEY_NULL)
   {
    break;
   }
   g_KeyInfo.Duration = 0;
   g_KeyInfo.Val        = m_ucKeyCode;
   for(m_ucKeyIndex=0;m_ucKeyIndex<Get_Max_Key();m_ucKeyIndex++)
   {
    if(c_aKeyParam_Tab[m_ucKeyIndex] == g_KeyInfo.Val)
    {
     break;
    }
   }
   if(m_ucKeyIndex == Get_Max_Key())
   {
    g_KeyInfo.Val = KEY_NULL;
    break;
   }
   g_KeyInfo.Status = KEY_EVENT_CHK_DISTURB;
   break;

  case KEY_EVENT_CHK_DISTURB:
   if(m_ucKeyCode == g_KeyInfo.Val)
   {
    g_KeyInfo.Status = KEY_EVENT_IS_PRESS;
   }
   else
   {
    g_KeyInfo.Status = KEY_EVENT_IDLE;
   }
   break;

  case KEY_EVENT_IS_PRESS:
   //Set_Key(MSG_KEY|(PRESS_KEY_DOWN|KEY_PRESS_SHORT)|g_KeyInfo.Val);
   g_KeyInfo.Status = KEY_EVENT_CHK_HOLD;
   g_KeyInfo.Duration = 0;
   break;

  case KEY_EVENT_CHK_HOLD:
   if(m_ucKeyCode == g_KeyInfo.Val)
   {
    if(++g_KeyInfo.Duration >= TICK_TH_LONG_PRESS)
    {
     Set_Key(MSG_KEY|(PRESS_KEY_DOWN|KEY_PRESS_LONG)|g_KeyInfo.Val);
     g_KeyInfo.Status = KEY_EVENT_CHK_CONTINUE;
     g_KeyInfo.Duration = 0;
    }
   }
   else
   {
    goto KEY_RELEASE_LABLE;//g_KeyInfo.Status = KEY_EVENT_CHK_RELEASE;
   }
   break;
   
  case KEY_EVENT_CHK_CONTINUE:
   if(m_ucKeyCode == g_KeyInfo.Val)
   {
    if(++g_KeyInfo.Duration >= TICK_TH_LONG_PRESS)
    {
     Set_Key(MSG_KEY|(PRESS_KEY_DOWN|KEY_PRESS_LONG|KEY_HOLD_CNT_LONG)|g_KeyInfo.Val);
     g_KeyInfo.Duration = 0;
    }
    else
    {
     if((g_KeyInfo.Duration%TICK_TH_SHORT_PRESS) == 0)
     {
      Set_Key(MSG_KEY|(PRESS_KEY_DOWN|KEY_PRESS_LONG|KEY_HOLD_CNT_SHORT)|g_KeyInfo.Val);
     }
    }
    break;
   }
   
KEY_RELEASE_LABLE:   
  case KEY_EVENT_CHK_RELEASE:
   if((g_KeyInfo.Status == KEY_EVENT_CHK_HOLD) && (g_KeyInfo.Duration < TICK_TH_LONG_PRESS))
   {
    Set_Key(MSG_KEY|(PRESS_KEY_DOWN|KEY_PRESS_SHORT)|g_KeyInfo.Val);
    g_KeyInfo.Status = KEY_EVENT_IDLE;
    break;
   }
   Set_Key(MSG_KEY|(PRESS_KEY_UP|KEY_PRESS_SHORT)|g_KeyInfo.Val);
   g_KeyInfo.Status = KEY_EVENT_IDLE;
   break;
}
}

void Key_Proc(void)
{
UINT16 m_uiKeyCodeHead;
static uint32 m_ulKeuTick=0;

if(get_system_ms()-m_ulKeuTick < 10L)
{
  return;
}
m_ulKeuTick = get_system_ms();

Clr_Key();
Key_Event(Get_AdKeyCode());

m_uiKeyCodeHead = Get_Msg_Type();
if((m_uiKeyCodeHead != MSG_KEY)&&(m_uiKeyCodeHead != MSG_IR))
{
  return;
}
        lastProcessTick = get_system_ms();
        if(display_open() == TRUE)
        {
        Clr_Key();
        }
if(If_Key_Null())
{
  return;
}

switch(Get_Key_Val())
{
   case KEY_NEXT:
    if(If_Key_Press_Short())
    {
     UserCmd = USER_CMD_NEXT;
     break;
    }
    if(If_Key_Hold_Cnt_Short())
    {
     UserCmd = USER_CMD_FFWD;
     break;
    }
    if(If_Key_Hold_Cnt_Long())
    {
     UserCmd = USER_CMD_FFWD;
     break;
    }
    break;

   case KEY_PREV:
    if(If_Key_Press_Short())
    {
     UserCmd = USER_CMD_PREV;
     break;
    }
    if(If_Key_Hold_Cnt_Short())
    {
     UserCmd = USER_CMD_FBWD;
     break;
    }
    if(If_Key_Hold_Cnt_Long())
    {
     UserCmd = USER_CMD_FBWD;
     break;
    }
    break;

   case KEY_VOLUP:
    if(If_Key_Press_Short())
    {
     UserCmd = USER_CMD_VOLUP;
     break;
    }
    if(If_Key_Press_Long())
    {
     UserCmd = USER_CMD_VOLUP;
     break;
    }
    if(If_Key_Hold_Cnt_Short())
    {
     UserCmd = USER_CMD_VOLUP;
     break;
    }
    if(If_Key_Hold_Cnt_Long())
    {
     UserCmd = USER_CMD_VOLUP;
     break;
    }
    break;

   case KEY_VOLDN:
    if(If_Key_Press_Short())
    {
     UserCmd = USER_CMD_VOLDN;
     break;
    }
    if(If_Key_Press_Long())
    {
     UserCmd = USER_CMD_VOLDN;
     break;
    }
    if(If_Key_Hold_Cnt_Short())
    {
     UserCmd = USER_CMD_VOLDN;
     break;
    }
    if(If_Key_Hold_Cnt_Long())
    {
     UserCmd = USER_CMD_VOLDN;
     break;
    }
    break;
   
   case KEY_ENTER:
    if(If_Key_Press_Short())
    {
     UserCmd = USER_CMD_ENTER;
     break;
    }
    if(If_Key_Press_Long())
    {
     UserCmd = USER_CMD_MENU;
     break;
    }
    break;
   
   default:
    break;
}
}
#endif

出0入0汤圆

发表于 2013-7-23 19:41:02 | 显示全部楼层
Eiman 发表于 2013-7-23 16:19
这个如何呢?思路比较清晰!
#ifdef SARADC_KEY_ENABLE//Add by EimanFeng 2013-07-03
#define KEY_SCAN_CF ...

嘿,BOSS,现在看到了!

出0入0汤圆

发表于 2014-11-24 17:42:45 | 显示全部楼层
不错  学习了

出0入0汤圆

发表于 2016-5-12 23:58:14 | 显示全部楼层
需要,收藏,哈哈

出0入0汤圆

发表于 2017-7-23 21:46:47 | 显示全部楼层
先收藏,谢谢!

出0入0汤圆

发表于 2019-4-24 09:00:56 | 显示全部楼层
先收藏,谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-24 15:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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