面向对象的C语言(OOPC)之按键

  • zhangsf_chongza
  • LV5工程师
  • |      2016-03-31 16:24:30
  • 浏览量 899
  • 回复:1

概述


在嵌入式系控制系统中,通常使用按键(Key)来实现人机交互,完成一些控制功能。一般地,按键在按下(KeyDown)和抬起(KeyUp)的过程中会存在1020ms的抖动毛刺,为了获取稳定的按键信息,必须通过一定的方法来避开这段不稳定的抖动期。


本文介绍了一种软件去抖动的方法,并采用面向对象的程序设计,将按键进行封装起来,对外提供统一的接口,生成单独的按键驱动文件,便于程序的移植(程序在STM32F103(ST)M16C/62P (RENESAS)系统上调试通过)。


1          按键软件去抖方法


1.1         按键在按下(KeyDown)和抬起(KeyUp)的过程中会存在1020ms的抖动毛刺,软件采用“2回一致”原则,主循环中每25ms对按键输入口进行采样,如果连续2次采样一致,则确认按键的输入信息。


点击看大图


1.2         Key输入确认后,可以在确认值的“上升沿”(上图中水绿色的1处)触发KeyUp抬起事件,在“下降沿”(上图中粉色的0处)触发KeyDown事件。同样,也可以通过计数器来触发长按键KeyPress事件。


 


2          OOPC(面向对象的C语言)


对于嵌入式系统的开发,OOPC是一个非常不错的选择,既有C语言的小巧、高效性,又有C++的封装、继承。笔者学习了高焕堂先生编写的《UML+OOPC嵌入式C语言开发精讲》,获益匪浅。本按键驱动文件就是使用了书中OOPC的思想完成。我的理解还不够深刻,在这里只是抛砖引玉,大家互相交流。


MCU硬件资源越发强悍的今天,感觉嵌入式系统的开发者也过上了“有钱人”的生活,不需要再节衣缩食,过多的考虑ROM/RAM的占用以及代码的运行速度,而可以更加注重软件的可重用性、可维护性等。


按键程序分3个文件:KeyDrv.hKeyDrv.cKeyApp.c。其中KeyDrv.hKeyDrv.c属于驱动文件,KeyApp属于应用文件。对于用户而言,只需要在KeyApp文件中的KeyUp/Down/Press事件中编写自己的应用程序即可,代码非常清爽。


 


3          Key的功能


(1)实现按键的三种事件(抬起KeyUp、按下KeyDown、长按KeyPress)


(2) KeyPress事件的变速度触发(例如:开始2s触发1次,再1s触发1次,最后40ms触发1次。时间可设)


(3)可选择按键长按再弹起时是否触发KeyUp事件(默认不触发)


(4)可选择按键长按是否多次触发KeyPress事件(默认不触发)


 


4          接口函数: 3个设定,1个按键扫描,3个服务,


4.1         3个设定(可以在进入主循环前进行设定---reset


set_KeyPin()                    //设置按键的位置,在MCU哪个引脚上


set_KeyPressUpCmd ()         //使能(失能)按键长按再弹起时是否触发KeyUp事件


set_KeyPressContinuedCmd ()  //使能(失能)按键长按是否多次触发KeyPress事件


4.2         按键扫描 (主循环中每隔20~25ms调用,推荐25ms调用1次)


KeyScan()                      //按键扫描,确认按键状态,并自动触发下面3跟服务类的事件


4.3         3个服务(在KeyApp文件中,可以在3个服务函数中写应用程序)


KeyUp ()                       //抬起事件


KeyDown ()                    //按下事件


KeyPress ()                    //长按事件


对于用户而言,只需要在KeyApp文件中的KeyUp/Down/Press事件中编写自己的应用程序即可,代码非常清爽,同时便于移植。


 


5          用法详细示例


* (1) reset函数中


     (a)包含key的头文件


     (b)定义按键指针变量并初始化(例定义4Key)


     (c)设置按键与MCU引脚对应,并设置相关属性


      * #include "KeyDrv.h"


      定义按键指针变量(最多可以创建256Key)-----------------------


        TKey *Key1,*Key2;


      按键指针初始化----------------------------------------------


        Key1 = (TKey *)NewKey();


        Key2 = (TKey *)NewKey();


      按键pin对应-------------------------------------------------


        Key1->IA.set_KeyPin(Key1,(u32 *)GPIOA,GPIO_Pin_0);


        Key2->IA.set_KeyPin(Key2,(u32 *)GPIOC,GPIO_Pin_13);


      使能(失能)长按键后的UP事件(ENABLE:触发;DISABLE:不触发)-


        Key1->IA.set_KeyPressUpCmd(Key1, DISABLE);


        Key2->IA.set_KeyPressUpCmd(Key2, DISABLE);


      使能(失能)长按是否多次触发KeyPress事件(ENABLE:触发;DISABLE:不触发)-


        Key1->IA.set_KeyPressContinuedCmd(Key1, ENABLE);


        Key2->IA.set_KeyPressContinuedCmd(Key2, ENABLE);


 


* (2)main主循环中调用扫描函数(25ms扫描1),程序自动检测按键状态并触发相关事件


      #include "KeyDrv.h"


        Key1->IA.KeyScan(Key1,1); //按键pin扫描


        Key2->IA.KeyScan(Key2,2); //按键pin扫描


    


* (3)KeyApp文件的相关事件中编写应用程序(idx为按键的索引号,main函数扫描时指定)


      #include "KeyDrv.h"


      按键抬起 ------------------------------------------------


      void KeyUp(const u8 idx)


      {


      }


      按键按下 ------------------------------------------------


      void KeyDown(const u8 idx)


      {


      }


      按键长按 ------------------------------------------------


      void KeyPress(const u8 idx)


      {


      }


 


6          备注 程序中运用的技巧:


用局部变量防止指针别名引起的重载,详见《arm嵌入式系统开发:软件设计与优化》第5 高效的C编程


7          附录:《KeyApp.c》、《KeyDrv.h》、《DeyDrv.c


 

  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:1
@曲终人散@ 2016-04-06
版面不错哟
0   回复
举报
发布
x
收藏成功!点击 我的收藏 查看收藏的全部帖子