切换到宽版
  • 2191阅读
  • 5回复

[C51]浅谈我的程序框架补充-按键示例 [复制链接]

上一主题 下一主题
离线南天音乐
 

发帖
180
M币
49
专家
5
粉丝
5
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2016-04-25
今天上午发了一个“浅谈我的单片机程序架构”的帖子,有点啰嗦,可能大家看不太下去。现在补充一个按键扫描实例,看对大家是否有所启发。
注意:此文不仅是程序架构,而且还提出了一种按键识别的解决方案,也属抛砖引玉,欢迎大家讨论。
【程序仅提供思想】
主框架结构(下面这个大家应该都很熟悉吧)
void main()
{
...//系统相关底层驱动初始化
  while(1)
  {
   ...//服务程序
   ...//应用程序
  }
}
开始填写框架
void main()
{
  ...//系统相关底层驱动初始化
while(1)
  {
  /*服务程序*/
  Input_Scan_Svr();//输入服务程序
  ...//应用程序
  }
}
输入服务程序包含什么呢,继续往下看
void Input_Scan_Svr()//系统输入服务
{
  /*针对按键的*/
  KeyScan_Svr();
  KeyIDEXC();//键码转换,将按键转换为系统能识别的键码
/*针对串口的*/
  ...
}
可以看到针对按键处理的1个子服务和1个转换进程。
来看看按键扫描服务程序(...代表其他按键相同写法)
/*服务程序*/
void KeyScan_Svr()//按键扫描服务程序
{
/*该服务程序给上层服务或应用提供按键状态信息(Keyx_State)*/
  static u8 Key1State_TC=0;//按键端口状态计时
   ...
  /*状态计时*/
  //按键1
  if(GetKey1State()==K_TRIGGERING)
   {
     if(Key1State_TC<127)//防止状态计时溢出
        Key1State_TC+=os_100ms;//每个扫描服务周期状态正向计时+100ms
   }
...
/*状态解析*/
//按键1
   if(GetKey1State()==K_NORMAL)//松键才识别
   {
     Key1_State=KEY_NO_PRESS;
     if(Key1State_TC>0)
     {
       if(PressCountA<5) Key1_State=KEY_SHORT_PRESS;//按下时间小于0.5s,视为短按
       else if(PressCountA<30) Key1_State=KEY_LONG_PRESS;//按下时间大于0.5s小于3秒,视为长按
       Key1State_TC=0; //状态计时清零
    }
  }
  if(Key1State_TC>=30)//按键1触发持续超过3秒,视为持续按下
    Key1_State=KEY_KEEP_PRESS;
   ...
}
可以看到这个扫描服务中调用了底层驱动程序GetKey1State();这个函数就很简单啦
/*驱动程序*/
u8 GetKey1State()//返回按键1端口状态
{
//IO_Key1 =Px^x
if(IO_Key1==0) return K_TRIGGERING;
else return K_NORMAL;
}
最后再来看看键码转换进程
void KeyIDEXC()//键码转换标准键码
{
  LocalKeyID=0;//初始化ID
  if(Key1_State==KEY_SHORT_PRESS)
    LocalKeyID=K_UP;
  else if(Key1_State==KEY_LONG_PRESS)
    LocalKeyID=K_ENTER;
  else if(Key1_State==KEY_KEEP_PRESS)
    LocalKeyID=K_F1;
  ...
//还可以随意补充按键组合,返回一个键码即可
}
上层应用程序能识别的键码就是K_UP、K_DOWN、K_ENTER...在这里我把这些键码和电脑键盘键码对应起来
#define K_ENTER                     13
#define K_ESC                          27
#define K_UP                            38
#define K_DOWN                      40
#define K_F1                            112
#define K_F2                            113
#define K_F3                            114
#define K_TAB                          9
#define K_HOME                      36
...
这就是按照我自己的架构写的按键识别的服务程序。至于按键状态计时中的os_100ms等时间脉冲,是由另外一个系统服务程序提供的,可以保证这些时间脉冲仅存在1个周期,在主逻辑执行周期小于这些时间脉冲时是准确有效的。所以完整的框架变成为
void main()
{
  NTOS_Init();//系统相关底层驱动初始化
  while(1)
{
/*服务程序*/
  NTOS_TimePulse_Svr();//时间脉冲服务,产生100ms,500ms,1s的计时脉冲
  Input_Scan_Svr();//输入服务程序,抓取外部输入信号
...//应用程序
}
}
当然,NTOS_TimePulse_Svr()服务还需用到内部定时器硬件,因此需写一个TimePulse的驱动,而这个驱动比较特殊,需要用到定时器罢了。
以上就是在我的程序框架下搭建按键识别服务的一个过程,看似有些麻烦和冗余,实际上却是条理清晰,这点,估计自己的框架只有自己懂了吧!再次欢迎大家提出更优秀的算法。
本帖最近打赏记录:共9条打赏 ,M币+85 ,专家+1

发帖
1318
M币
1226
专家
6
粉丝
61
只看该作者 1楼 发表于: 2016-04-25
请登录后查看
离线mosliu

发帖
29913
M币
14893
专家
2
粉丝
64
只看该作者 2楼 发表于: 2016-04-25
请登录后查看
离线flave

发帖
420
M币
1800
专家
-1
粉丝
30
只看该作者 3楼 发表于: 2016-04-26
请登录后查看
离线南天音乐

发帖
180
M币
49
专家
5
粉丝
5
只看该作者 4楼 发表于: 2016-04-26
回 flave 的帖子
请登录后查看
离线40303838

发帖
346
M币
1324
专家
1
粉丝
2
只看该作者 5楼 发表于: 2016-05-05
请登录后查看
快速回复
限80 字节
“新手上路”发帖需审核后才能显示(请认真发帖),达到数码9级后取消此限制
 
上一个 下一个