slzm40 发表于 2014-11-27 16:16:44

<交流一下> 偷师傻孩子,自己用的简单测试模板-测试按键

本帖最后由 slzm40 于 2014-11-28 10:21 编辑

           在傻孩子这个专栏偷师了许久,觉得有必要发出来交流下,顺便听听大家的批评声,以促进自己更大的进步。
        因为是测试小模板,用于测试一些小功能的,所有有些要求并不高,比如串口调试 用的不是循环队列的中断方式,而是用等待方式。
       
        /********测试小模板说明 - 2014-11-27*********/
        模板功能: 有串口回显功能, 时间触发式小系统,延时模块调用,对象方法的使用,宏方法使用
        模板来源:至少80%偷师于傻孩子,因为是自己重编过,所以没有在注释里留下来源,但变量用名等大部份保留原来的格式,有一些修改也只是适用在自己的风格。
        /********测试小模板说明*********/
        *另外由于PIC不支持掩码结构体,所以在对对象方法的简单使用中,做了修改,本次没有使用,但宏有放在H文件中,简单的其实是结构体。*/

        /*本次主要测试功能,按键功能。*/   

        上次对通用按键模块做了分析和学习, 在通用模块中开了两个队列, 占有了不少的空间,所以我自己修改了下按键模块,去除队列,加入消息传输,以适用于自己的平台。
        按键模块大部份变量和思想 基于傻孩子专栏的 通用按键模块。 也是状态机!
       
        简单说下自己这个按键模块的使用,由于本人属于水平有限。有BUG的地方提出来,以便修正和提高。
        和通用按键模块基本一样的顺序列:

        1、编写按键获取键值函数

        需要编写自己的按键键值获取函数。放在keyqueue.c中(我够懒的,里面不是队列方式)
       
        对了,我是高电平获得按键,平时低电平。
        /*这个是需要更改的*/
static uint8_t bsp_key_scan_value()
{
    if( IO_KEY_K1 )
    {
      return KEY_PRESS_K1;
    }
    if( IO_KEY_K2)
    {
      return KEY_PRESS_K2;
    }
    return KEY_NULL;
}

        在keyqueue.h中可以拓展按键,可以修改滤波,长击,连击时间,可以拓展按键。
        然后,我的按键只有三种状态,短按,长按,连击,其它的没有做。
//时基为10ms
//用于定义按键滤波,长击,连击时间
#define KEY_FILTER_TIME                2
#define KEY_LONG_TIME                  10
#define KEY_REPEAT_TIME                3

/*用于拓展按键,需要修改*/
typedef enum
{
        KEY_NULL = 0,                /* 0 表示按键事件 */       
        KEY_PRESS_K1,                /* k1按键 */
        KEY_PRESS_K2,                /* k2按键*/
        //KEY_PRESS_K3,                /* k3按键 */
        //KEY_PRESS_K4                /* k3按键 */
}key_value_t;


在初始化于配置IO口
void bsp_Key_init(void)
{
        /*按键硬件配置*/
        KEY_K1_INPUT();//按键输入
        KEY_K2_INPUT();//按键输入

        /*消息创建*/
        KeyMsgCreate(&s_tKeyEventMsg,&s_tKeyDetectorMsg);//创建获得键消息
}

       
        2、接口使用说明
        经过以上的修改,keyqueue.h: 三个函数就可以使用了。

        void bsp_decetor_Key_Task(void);
        void bsp_Key_init(void);
        bool bsp_GetKey(key_event_t *ptkey);
      
       bsp_Key_init();初始化调用
       bsp_decetor_Key_Task(); 在超级循环里调用,我是设成10ms调用一次,配合触发式小系统
       bsp_GetKey()可以获得键值,有键值时返回true,
       
        超级循环:
        void main(void)
{
    …
    init_key_task();
    …
    while(1) {   
    …
    //需要在超级循环或者定时器中断处理程序中被周期性的调用
   if(10ms到)
{   
    bsp_decetor_Key_Task();
}
        Keydeal_loop();   

    }
}

       
        按键使用:
        void Keydeal_loop(void)
{
           key_event_t keycode = {KEY_NULL,KEY_NONE_PRESSED};
        if(bsp_GetKey(&keycode))
                {
                if(KEY_PRESSED == keycode.tEvent)//短按
                        {
                        if(KEY_PRESS_K1 == keycode.chKeyValue)
                                {
                                sprint("key1 short press!\n");
                                }

                        if(KEY_PRESS_K2 == keycode.chKeyValue)
                                {
                                sprint("key2 short press!\n");
                                }
                        }
                if(KEY_LONG_PRESSED == keycode.tEvent)//长按
                        {
                        if(KEY_PRESS_K1 == keycode.chKeyValue)
                                {
                                sprint("key1 long press!\n");
                                }
                        if(KEY_PRESS_K2 == keycode.chKeyValue)
                                {
                                sprint("key2 long press!\n");
                                }
                        }
                if(KEY_REPEAT_PRESSED == keycode.tEvent)//连击
                        {
                        if(KEY_PRESS_K1 == keycode.chKeyValue)
                                {
                                sprint("key1 repeat press!\n");
                                }
                        if(KEY_PRESS_K2 == keycode.chKeyValue)
                                {
                                sprint("key2 repeat press!\n");
                                }                       
                        }
        }
}


       
        我用的是proteus仿真,Virtual serial port做串口测试;



        结果:
       

        还是传文件吧,欢迎批评。 以求编程水平提高。


/****修改kqueue里 KEY_MSG和key_event_t 多定义的问题****/
/****修改kqueue里有无消息事件 改成枚举,未修正问题。 ****/


       

slzm40 发表于 2014-11-27 16:18:26

本帖最后由 slzm40 于 2014-11-28 10:20 编辑

****************************************
说明一下,大部份源码来源于本专栏。


传不上附件。。。

slzm40 发表于 2014-11-27 16:24:02

slzm40 发表于 2014-11-27 16:18
****************************************
说明一下,大部份源码来源于本专栏。



在增加按键使用时,只需修改.h文件中的
/*用于拓展按键,需要修改*/
typedef enum
{
        KEY_NULL = 0,                /* 0 表示按键事件 */       
        KEY_PRESS_K1,                /* k1按键 */
        KEY_PRESS_K2,                /* k2按键*/
        //KEY_PRESS_K3,                /* k3按键 */
        //KEY_PRESS_K4                /* k3按键 */
}key_value_t;

和/*这个是需要更改的*/
static uint8_t bsp_key_scan_value()
{
    if( IO_KEY_K1 )
    {
      return KEY_PRESS_K1;
    }
    if( IO_KEY_K2)
    {
      return KEY_PRESS_K2;
    }
    return KEY_NULL;
}


两个地方和配置硬件IO放入初始化,就可以调用了。。bsp_decetor_Key_Task()放入10ms的时基里,bsp_GetKey()就可以使用了。 修改地方为四处。

机器人天空 发表于 2014-11-27 16:32:40

状态机{:lol:}

Gorgon_Meducer 发表于 2014-11-28 09:51:32

赞!还没来得及看你的代码,但希望你学习到信息分级处理的思想,这也是模式识别的基本方法。比如手势识别就是用信息分级

slzm40 发表于 2014-11-28 10:01:57

本帖最后由 slzm40 于 2014-11-28 10:19 编辑

static KEY_MSG s_tKeyEventMsg;
static key_event_t s_tKeyDetectorMsg;//定义消息内存

在kqueue.c中多定义的了一次,有看代码的,可以把里面删掉一份。

我重新传一份

/****修改kqueue里 KEY_MSG和key_event_t 多定义的问题****/
/****修改kqueue里有无消息事件 改成枚举,未修正问题。 ****/

slzm40 发表于 2014-11-28 10:04:42

本帖最后由 slzm40 于 2014-11-28 10:12 编辑

Gorgon_Meducer 发表于 2014-11-28 09:51
赞!还没来得及看你的代码,但希望你学习到信息分级处理的思想,这也是模式识别的基本方法。比如手势识别就 ...

正在学习中,简单点说,从专栏里学到无阻塞状态机方法,面向对象,分层。
至于信息分级处理思想还有多多思考写代码中慢慢继续领悟。

等你新书啊!

eryueniao 发表于 2015-12-25 15:43:16

bsp_decetor_Key_Task();这个函数怎么没有贴出来                        

yanzhiwei 发表于 2015-12-26 15:24:30

收藏看看,谢谢分享。弱弱的问一句,楼主用的是什么串口调试软件,能放上来共享么

zenghl 发表于 2015-12-26 15:55:10

赞一个!
{:lol:}

desireyao 发表于 2015-12-27 15:48:01

下载下来学习一下
页: [1]
查看完整版本: <交流一下> 偷师傻孩子,自己用的简单测试模板-测试按键