foxpro2005 发表于 2012-7-5 21:47:20

写了一个独立按键 支持组合键、单键长按,连发功能的例子

本帖最后由 foxpro2005 于 2012-7-5 21:53 编辑

学习了马老师的《AVR单片机嵌入式系统原理与应用实践书》 第2版,现也写了一个按键扫描的例子(用WINAVR写的)。
独立按键,支持组合键,单键长按,连发功能等应用,已通过实践测试。

KeyScan.h 部分
/********************************************************************************************************
* FileName....:        KeyScan.h
* MCU.........:        ATmega8 at 8MHz
* Compiler....:        WinAVR-20100110
* Author......:        foxpro2005
* Ver.........:        V1.0
* Time........:        2012.07.04
* Description.:        Key scan.
* History.....:        2012.07.04 V1.0
*
******************************************************************************************************/
#ifndef _KeyScan_H_
#define _KeyScan_H_

//------------------------------------------------------------------------------------------------------
#include <avr/io.h>                               

//-------------------------------------------------------------------------------------------------------
/*****************************硬件I/O引脚定义,根据实际应用修改******************************/
#define KEY_PORT        PIND                                                                        // 独立按键所占用端口.

#define K_STOP                (1<<PD3)                                                                // "停止"键
#define K_START        (1<<PD4)                                                                // "启动"键
#define K_SEL                (1<<PD5)                                                                // "选择"键
#define K_ADD                (1<<PD6)                                                                // "+ "键
#define K_DEC                (1<<PD7)                                                                // "- "键

#define OneKeyTime        300                                                                                // 单键长按时长 = OneKeyTime * 10ms
#define MuxKeyTime        500                                                                                // 组合键长按时长 = MuxKeyTime * 10ms
#define RepeatTime        5                                                                                // 单键连发功能重复间隔时间 = RepeatTime * 10ms

#define Key_Mask        (K_STOP|K_START|K_SEL|K_ADD|K_DEC)                        // 按键掩码值

//-------------------------------------------------------------------------------------------------------
#define GetKey()        (KEY_PORT & Key_Mask)                                                // 读取按键端口值

#define key_state_0        0                                                                                // 初始态.
#define key_state_1        1                                                                                // 确认态.
#define key_state_2        2                                                                                // 组合键,长按键确认态.
#define key_state_3        3                                                                                // 长按连发功能确认态.
#define key_state_4        4                                                                                // 等待释放态.

//-------------------------------------------------------------------------------------------------------
/****************************************数据类型定义**************************************/
typedef enum {NO_KEY,STOP,START,SEL,ADD,DEC,SETUP} eKEY;        // 按键返回值类型定义.

//-------------------------------------------------------------------------------------------------------
/*****************************************函数声明****************************************/
eKEY ReadKey(void);                                                                                        //读取按键.                                       

//-------------------------------------------------------------------------------------------------------
#endif


KeyScan.c 部分
/********************************************************************************************************
* FileName....:        KeyScan.c
* MCU.........:        ATmega8 at 8MHz
* Compiler....:        WinAVR-20100110
* Author......:        foxpro2005
* Ver.........:        V1.0
* Time........:        2012.07.04
* Description.:        Key scan.
* History.....:        2012.07.04 V1.0
*
******************************************************************************************************/
//------------------------------------------------------------------------------------------------------
#include "KeyScan.h"

//------------------------------------------------------------------------------------------------------
/***********************************全局变量定义区******************************************/


/********************************************************************************************
* eKEY ReadKey(void);
* 功能: 独立按键扫描,10ms扫描一次.
* 返回值:枚举类型,{NO_KEY,STOP,START,SEL,ADD,DEC,SETUP}.
* 参数:
********************************************************************************************/
eKEY ReadKey(void)
{
        static unsigned int key_time = 0;                                                        // 长按键计时
        static unsigned char key_state = 0;                                                // 记录按键扫当前描状态
        static unsigned char key_press_old = 0;                                        // 记录上一次按键状态
        static eKEY key_value_old = NO_KEY;                                                // 保存上一次按键返回值
        eKEY key_return = NO_KEY;                                                                // 按键功能返回值
        unsigned char key_press;
       
        key_press = GetKey() ^ Key_Mask;                                                // 读按键I/O电平,只保留被按下的键(被按下的键位为1)
        switch (key_state)
        {
                case key_state_0:                                                                // 1.按键初始态
                        if (key_press)
                        {
                                key_state = key_state_1;                                        // 键被按下,状态转换到按键确认态
                                key_press_old = key_press;                                // 保存当前按键状态
                        }
                        break;
                case key_state_1:                                                                // 2.按键确认态
                        if (key_press == key_press_old)                                        // 与初始态的按键状态相同?
                        {
                                key_time = 0;                                                        // 清另按键时间计数器
                                switch(key_press)
                                {
                                        case K_STOP:
                                                key_state= key_state_4;                         // 转按键释放态
                                                key_return = STOP;                                // "停止"键
                                                break;
                                        case K_START:
                                                key_state= key_state_4;                         // 转按键释放态
                                                key_return = START;                                // "起动"键                                               
                                                break;       
                                        case K_SEL:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = SEL;                                // "选择"键                                                               
                                                break;       
                                        case K_ADD:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = ADD;                                // "+"键
                                                break;       
                                        case K_DEC:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = DEC;                                // "-"键
                                                break;
                                        case K_STOP|K_SEL:                                        // "组合"键,长按键
                                                key_state= key_state_2;                         // 组合键按键仍按下,状态转换到计时1
                                                break;       
                                        default:
                                                key_state= key_state_4;                         // 转按键释放态
                                                break;
                                }
                        }
                        else if (!key_press)
                          key_state = key_state_0;                                        // 按键已抬起(是干扰),转换到按键初始态
                        else
                                key_state = key_state_4;                                        // 按键已发生变化,转到按键释放态
                               
                        key_value_old = key_return;                                        // 保存按键返回值
                        break;
                case key_state_2:                                                                // 3.长按键确认态
                        if (key_press == key_press_old)
                        {
                                ++key_time;                                                        // 按键计时
                                if (key_press == (K_STOP|K_SEL))                        // "配置"键?
                                {
                                        if(key_time >= MuxKeyTime)                        // 组合键长按计时
                                        {
                                                key_state = key_state_4;                        // 按下时间>=MuxKeyTime,转到按键释放状态
                                                key_return = SETUP;                                // 组合键功能,"配置"键
                                        }
                                }
                                else
                                {
                                        if(key_time >= OneKeyTime)                        // 单键长按计时
                                        {
                                                key_state = key_state_3;                        // 按下时间>=OneKeyTime,转到连发功能态,用于触发连发功能
                                                key_time = 0;                                        // 清按键计数器
                                                key_return = key_value_old;                // 返回上一次按键值
                                        }
                                }
                        }
                        else
                                key_state = key_state_4;                                        // 按键已发生变化,转到按键释放态
                        break;
                case key_state_3:                                                                // 4.按键连发功能
                        if (key_press == key_press_old)
                        {
                                if (++key_time >= RepeatTime)                                // 按键时间计数
                                {
                                        key_time = 0;                                                // 按下时间>=0.05s,清0按键计数器
                                        key_return = key_value_old;                        // 返回上一次按键值
                                }                               
                        }
                        else
                          key_state = key_state_4;                                         // 按键已发生变化,转到按键释放态
                        break;
                case key_state_4:                                                                // 5.等待所有按键释放开
                        //if (!key_press)                                                                // 等待所有按键释放,才进入一次新的按键确认过程
                        if (key_press != key_press_old)                                        // 按键发生变化,就进入一次新的确认过程
                          key_state = key_state_0;                                         // 按键已释放,转换到初始态.
                        break;                       
        }       
    return key_return;
}

yupusong@qhd 发表于 2012-7-6 18:25:08

你好,我在调试你贴上的程序,发现单个按键都正常,为什么组合键就不正常呢?代码如下:

#include <iom16v.h>

#define K_STOP                (1<<PA0)                                                                // "停止"键
#define K_START               (1<<PA1)                                                                // "启动"键
#define K_SEL               (1<<PA2)                                                                // "选择"键
#define K_ADD               (1<<PA3)                                                                // "+ "键
#define K_DEC               (1<<PA4)                                                                // "- "键

#define OneKeyTime      300                                                                         // 单键长按时长 = OneKeyTime * 10ms
#define MuxKeyTime      500                                                                         // 组合键长按时长 = MuxKeyTime * 10ms
#define RepeatTime      5                                                                           // 单键连发功能重复间隔时间 = RepeatTime * 10ms

#define Key_Mask      (K_STOP|K_START|K_SEL|K_ADD|K_DEC)                        // 按键掩码值


#define KEY_PORT            PORTA                                                                  // 独立按键所占用端口.
#define KEY_DDR                                  DDRA
#define KEY_PIN                                  PINA
//-------------------------------------------------------------------------------------------------------
#define GetKey()      (KEY_PIN & Key_Mask)                                                // 读取按键端口值

#define key_state_0      0                                                                              // 初始态.
#define key_state_1      1                                                                              // 确认态.
#define key_state_2      2                                                                              // 组合键,长按键确认态.
#define key_state_3      3                                                                              // 长按连发功能确认态.
#define key_state_4      4                                                                              // 等待释放态.

//-------------------------------------------------------------------------------------------------------
/****************************************数据类型定义**************************************/
typedef enum {NO_KEY,STOP,START,SEL,ADD,DEC,SETUP} eKEY;      // 按键返回值类型定义.

//-------------------------------------------------------------------------------------------------------
/*****************************************函数声明****************************************/
eKEY ReadKey(void);                                                                                        //读取按键.                                       

//-------------------------------------------------------------------------------------------------------
unsigned char time_counter,key_stime_counter;                // 时间计数单元
unsigned char point_on, time_1s_ok,key_stime_ok;



/********************************************************************************************
* eKEY ReadKey(void);
* 功能: 独立按键扫描,10ms扫描一次.
* 返回值:枚举类型,{NO_KEY,STOP,START,SEL,ADD,DEC,SETUP}.
* 参数:
********************************************************************************************/
eKEY ReadKey(void)
{

      static unsigned int key_time = 0;                                                      // 长按键计时
      static unsigned char key_state = 0;                                                // 记录按键扫当前描状态
      static unsigned char key_press_old = 0;                                        // 记录上一次按键状态
      static eKEY key_value_old = NO_KEY;                                                // 保存上一次按键返回值
      eKEY key_return = NO_KEY;                                                                // 按键功能返回值
      unsigned char key_press;

      key_press = GetKey() ^ Key_Mask;                                                // 读按键I/O电平,只保留被按下的键(被按下的键位为1)
      
               
                switch (key_state)
      {
                case key_state_0:                                                                // 1.按键初始态
                        if (key_press)
                        {
                              key_state = key_state_1;                                        // 键被按下,状态转换到按键确认态
                              key_press_old = key_press;                                    // 保存当前按键状态
                        }
                                               
                        break;
                case key_state_1:                                                                                                                              // 2.按键确认态
                        if (key_press == key_press_old)                                       // 与初始态的按键状态相同?
                        {
                              key_time = 0;                                                      // 清另按键时间计数器
                              switch(key_press)
                              {
                                        case K_STOP:
                                                key_state= key_state_4;                         // 转按键释放态
                                                key_return = STOP;   
                                                                                                                           // "停止"键
                                                break;
                                        case K_START:
                                                key_state= key_state_4;                         // 转按键释放态
                                                key_return = START;                              // "起动"键                                                
                                                break;      
                                        case K_SEL:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = SEL;                              // "选择"键                                                               
                                                break;      
                                        case K_ADD:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = ADD;                              // "+"键
                                                break;      
                                        case K_DEC:
                                                key_state= key_state_2;                         // 转长按键态
                                                key_return = DEC;                              // "-"键
                                                break;
                                        case K_STOP|K_SEL:                                        // "组合"键,长按键
                                                key_state= key_state_2;                         // 组合键按键仍按下,状态转换到计时1
                                                break;      
                                        default:
                                                key_state= key_state_4;                         // 转按键释放态
                                                break;
                              }
                        }
                        else if (!key_press)
                            key_state = key_state_0;                                        // 按键已抬起(是干扰),转换到按键初始态
                        else
                              key_state = key_state_4;                                        // 按键已发生变化,转到按键释放态
                              
                        key_value_old = key_return;                                        // 保存按键返回值
                                               
                        break;
                case key_state_2:                                                                // 3.长按键确认态
                        if (key_press == key_press_old)
                        {
                              ++key_time;                                                      // 按键计时
                              if (key_press == (K_STOP|K_SEL))                        // "配置"键?
                              {
                                        if(key_time >= MuxKeyTime)                        // 组合键长按计时
                                        {
                                                key_state = key_state_4;                        // 按下时间>=MuxKeyTime,转到按键释放状态
                                                key_return = SETUP;                              // 组合键功能,"配置"键
                                        }
                              }
                              else
                              {
                                        if(key_time >= OneKeyTime)                        // 单键长按计时
                                        {
                                                key_state = key_state_3;                        // 按下时间>=OneKeyTime,转到连发功能态,用于触发连发功能
                                                key_time = 0;                                        // 清按键计数器
                                                key_return = key_value_old;                // 返回上一次按键值
                                        }
                              }
                        }
                        else
                              key_state = key_state_4;                                        // 按键已发生变化,转到按键释放态
                        break;
                case key_state_3:                                                                // 4.按键连发功能
                        if (key_press == key_press_old)
                        {
                              if (++key_time >= RepeatTime)                              // 按键时间计数
                              {
                                        key_time = 0;                                                // 按下时间>=0.05s,清0按键计数器
                                        key_return = key_value_old;                        // 返回上一次按键值
                              }                              
                        }
                        else
                            key_state = key_state_4;                                       // 按键已发生变化,转到按键释放态
                        break;
                case key_state_4:                                                                // 5.等待所有按键释放开
                        //if (!key_press)                                                                // 等待所有按键释放,才进入一次新的按键确认过程
                        if (key_press != key_press_old)                                        // 按键发生变化,就进入一次新的确认过程
                            key_state = key_state_0;                                       // 按键已释放,转换到初始态.
                        break;                        
      }   
               
               
    return key_return;
}



void Key_init(void)
{
    KEY_DDR&=~ (K_STOP)|(K_START)|(K_SEL)|(K_ADD)|(K_DEC);
    KEY_PORT |=(K_STOP)|(K_START)|(K_SEL)|(K_ADD)|(K_DEC);

}
void Timer0_Init(void)
{
        // T/C0 初始化
        TCCR0 = 0x0C;                        // 内部时钟,64分频(4M/64=62.5KHz),CTC模式
        TCNT0 = 0x00;
        OCR0 = 0x08;                        // OCR0 = 0x7C(124),(124+1)/62.5=2ms
        //TIMSK = 0x02;                        // 允许T/C0比较匹配中断
        TIMSK |=(1<<OCIE0);//允许T/C0比较匹配中断
}


#pragma interrupt_handler Timer0_comp_isr:20
void Timer0_comp_isr(void)
{
    //display();                                                // LED扫描显示
        if (++key_stime_counter >=5)
        {
                key_stime_counter = 0;
                key_stime_ok = 1;                                // 10ms到
                if (++time_counter >= 100)
                {
                        time_counter = 0;
                        time_1s_ok = 1;             // 1s到
                       
                }
        }


}

void main(void)
{
Buzz_init();
Key_init();
Timer0_Init();
SREG|=0x80;

while(1)
{
                if (key_stime_ok)                               
                {

                        key_stime_ok = 0;                                // 10ms到

                        //typedef enum {NO_KEY,STOP,START,SEL,ADD,DEC,SETUP} eKEY;
                        switch (ReadKey())
                        {
                                case STOP:
                                        Beep(1,1);

                                        break;
                                case START:       
                                        Beep(5,5);
                                        break;
                                       
                                case SEL:       
                                        Beep(10,10);
                                        break;
                                case ADD:       
                                        Beep(15,15);
                                        break;
                                case DEC:       
                                        Beep(20,20);
                                        break;
                                case SETUP:       
                                        Beep(130,130);
                                        break;
                        }

                }
}
}

foxpro2005 发表于 2012-7-6 20:52:13

yupusong@qhd 发表于 2012-7-6 18:25 static/image/common/back.gif
你好,我在调试你贴上的程序,发现单个按键都正常,为什么组合键就不正常呢?代码如下:

#include


....
#define OneKeyTime      300                                                                         // 单键长按时长 = OneKeyTime * 10ms
#define MuxKeyTime      500                                                                         // 组合键长按时长 = MuxKeyTime * 10ms
#define RepeatTime      5                                                                           // 单键连发功能重复间隔时间 = RepeatTime * 10ms
...

case K_STOP|K_SEL:                                        // "组合"键,长按键
...

本程序中,组合键,只定义了: STOP + SEL 键,并且要长按5S中 才会有效。

yupusong@qhd 发表于 2012-7-6 22:03:03

好的,多谢提示,我再试试看

yangling0 发表于 2012-7-7 06:59:38

好东西,正好要用,呵呵

yupusong@qhd 发表于 2012-7-7 08:45:02

多谢楼主的程序,已经调试通了,很实用{:victory:}

lcptw 发表于 2012-7-7 23:07:58

其实我是进来看看有没有其他平台的版本能借用的。{:loveliness:}

~伸手党~

2avr 发表于 2012-7-31 09:20:01

你这种风格不好,应该把按键扫描和按键功能执行分开,分别做成模块,

foxpro2005 发表于 2012-8-1 10:07:04

1.在这里只是按键的扫描部分,返回的仅是按键值而已(由枚举类型已定义好的,是只为了方便识别),是只代表是哪个按键按下(相当于一个标识符吧),并没有去具体定义按键的任何功能。
2.具体按键功能的实现(处理),是于由它的上层模块来完成。

糖烧熊 发表于 2012-11-27 14:07:05

{:smile:}{:smile:}{:smile:} 我试试看

guwu454 发表于 2013-9-4 10:23:58

嘿嘿!做次伸手党,谢谢大神,我好好理解一下!

wanglituan 发表于 2013-9-4 13:19:16

标记下。。。。

guwu454 发表于 2013-9-12 20:50:25

我想知道这个函数执行完了要多长时间,为什么我这个15ms还跑不完呢?

liumaojun_cn 发表于 2013-9-12 20:57:42

标记下,用的时候再看.

zbazba 发表于 2013-11-26 13:32:49

长按键跟短按键值返回都是一样,怎么在应用区别开来呢?

foxpro2005 发表于 2013-11-26 17:45:38

zbazba 发表于 2013-11-26 13:32
长按键跟短按键值返回都是一样,怎么在应用区别开来呢?

长按与短按返回的值不能一样,而持续按键实现连发功能 与 短按的返回的值是一样的。

zbazba 发表于 2013-11-27 09:21:49

foxpro2005 发表于 2013-11-26 17:45
长按与短按返回的值不能一样,而持续按键实现连发功能 与 短按的返回的值是一样的。

...

短按与长按肯定不能一样.但连发与短按返回值为什么能一样呢.应用怎么调用呢? 这个不解,呵呵.能告诉我下不?
可以这样处理,让短按的键值或上一个数值.返回这个.当然返回的数值不能跟别的冲突了.

foxpro2005 发表于 2013-11-27 12:04:20

连发就是相当于每次扫描的时候,把短按(正常操作)的值返回

jhjkdz 发表于 2013-11-28 11:56:04

学习。。。

mojinpan 发表于 2013-11-28 12:25:45

foxpro2005 发表于 2013-11-27 12:04
连发就是相当于每次扫描的时候,把短按(正常操作)的值返回

提供一个我写的功能类似的按键程序给大家做参考
传送门:http://www.amobbs.com/forum.php?mod=viewthread&tid=5558434&pid=7142055&page=1&extra=page%3D1#pid7142055

liuyongliuyong 发表于 2013-12-17 09:28:11

您好,楼主!看了你的程序,有点疑问想请教一下,你的程序是不是一个按键要么只能短按,要么只能长按,而不能一个按键同时具有短按,长按组合按的功能啊?

hunxiyi 发表于 2013-12-18 22:39:10

支持一个啊啊啊啊

白雪峰 发表于 2014-8-18 17:31:04

谢谢分享.....

second_chan 发表于 2014-8-20 15:00:38

谢谢分享,学习学习

papa0305 发表于 2014-8-20 20:49:21

参考一下      

ZJSXHWL000000 发表于 2014-9-8 16:48:07

组合键时.甜腻问题

zjb879653946 发表于 2014-10-17 10:05:08

这个按键程序遇到一个问题,就是当按键按下就会返回短按的状态,而不是抬起才返回,这样子无法实现短按和长按实现不同的功能

cece_co 发表于 2014-10-17 10:07:50

mark,按键少的时候很有用

qq303125686 发表于 2014-10-17 15:31:06

如果能够区分长按和短按就更好了

hamipeter 发表于 2014-10-17 17:08:39

支持一下!!!!!

阿文 发表于 2014-10-17 17:56:33

谢谢分享。。

zw_7627 发表于 2014-11-11 22:39:16

#include "Main.h"

eKEY ReadKey(void)        {
        static U16 key_time =0;                //长按键计时
        static U8 key_state = 0;        //记录按键当前扫描状态
        static U8 key_press_old = 0;        //记录上一次按键状态
        static eKEY key_value_old = NO_KEY;        //保存上一次按键返回值
        eKEY key_return = NO_KEY;        //按键功能返回值
        U8 key_press;
       
        key_press = GetKey()^ Key_Mask;        //读按键IO电平,只保留被按下的键(被按下的键位为1)
       
        switch (key_state)        {
                case key_state_0:        //按键初始态
                        if(key_press)        {
                                key_state = key_state_1;        //键被按下,状态转换到按键确认态
                                key_press_old = key_press;        //保存当前按键状态
                        }
                        break;
                case key_state_1:        //按键确认态
                        if(key_press == key_press_old)        //与初始态按键状态相同?
                        {
                                key_time = 0;        //清零
                                switch (key_press)
                                {
                                        case OPEN:        //case:K_OPEN ,这样写编译报错                                       
                                                key_state = key_state_4;        //转按键释放态
                                                key_return = OPEN;
                                                break;
                                       
                                        case CLOSE:                        //case:K_COLSE ,报错
                                                key_state = key_state_4;        //转按键释放态
                                                key_return = CLOSE;
                                                break;
                                       
                                        default:
                                                key_state = key_state_4;        //转按键释放态
                                                break;
                                }
                        }
                        else if(!key_press)       
                                key_state = key_state_0;        //按键已抬起(干扰),转初始态
                        else
                                key_state = key_state_4;        //按键已发生变化,转到按键释放态
                       
                        key_value_old = key_return;        //保存按键返回值
                       
                        break;       
                case key_state_4:        //等待所有按键释放开
                        if(key_press != key_press_old)        //按键发生变化,就进入一次新的确认过程
                                key_state = key_state_0;        //按键已释放,转换到初始态
                        break;
        }
        return key_return;
}


void LockProc(void)        {
        switch(ReadKey())        {
                case OPEN:
                                OpenLockOut();
                        break;
                case CLOSE:
                                ClosLockOut();
                        break;
                case NO_KEY:
                default:
                                ResetLock();
        }
}

void T10msEvent(void)        {
        LockProc();
}#ifndef        _PPQC_H
#define        _PPQC_H

#define        OpenLockOut()        do{OpenOut=1;ClosOut=0;}while(0)
#define        ClosLockOut()        do{OpenOut=0;ClosOut=1;}while(0)
#define ResetLock()                do{OpenOut=0;ClosOut=0;}while(0)

#define OneKeyTime        300                // 单键长按时长 = OneKeyTime * 10ms
#define MuxKeyTime500                // 组合键长按时长 = MuxKeyTime * 10ms
#define RepeatTime        5                // 单键连发功能重复间隔时间 = RepeatTime * 10ms

#define Key_Mask (K_CLOSE|K_OPEN)        //按键掩码值

#define GetKey()        (KEY_PORT & Key_Mask)        //读取按键端口值

#define key_state_0                0        //初始态
#define key_state_1                1        //确认态
#define key_state_2   2        //组合键,长按键确认态
#define key_state_3                3        //长按连发功能确认态
#define key_state_4                4        //等待释放态

typedef enum{NO_KEY,OPEN,CLOSE}eKEY;        //按键返回值类型定义

eKEY ReadKey(void);
void LockProc(void);
void T10msEvent(void);

#endif
我把这个应用到PIC16F1824中,编译器9.83,proteus仿真结果不对。不知道哪里出错了。

zw_7627 发表于 2014-11-11 22:56:44

CLOSEOUT一直有输出,K_CLOSE按下时,OPENOUT反而有输出。

zw_7627 发表于 2014-11-12 09:38:04

问题解决了。
1、对于CLOSEOUT一直有输出,在端口初始化中,将LATC=0放在TRISC=0前面;
2、对于K_CLOSE按下时,OPENOUT反而有输出。将key_state_1里面的switch语句,case OPEN和case CLOSE改成:case 3,和case 1。
疑问:
1、#define        K_CLOS                (1<<RA2) 和 K_OPEN                (1<<RA1),为什么PICC不能像楼主那样写成case K_CLOS 和K_OPEN;
2、为什么case OPEN和case CLOSE改成:case 3,和case 1就仿真成功?3和1是如何得到的?难道PICC将 K_OPEN                (1<<RA1)转换成了3?

zw_7627 发表于 2014-11-15 17:10:15

想了几天了,还是不明白#define      K_CLOS                (1<<RA2) ,为什么case :k_CLOS 通不过

foxpro2005 发表于 2014-11-15 20:13:53

zw_7627 发表于 2014-11-15 17:10
想了几天了,还是不明白#define      K_CLOS                (1

case 分支 必须是确定的常量 , 你好像是用的PIC单片机吧, RA2不是常量哦, 而是读取的引脚吧

zw_7627 发表于 2014-11-17 13:03:48

foxpro2005 发表于 2014-11-15 20:13
case 分支 必须是确定的常量 , 你好像是用的PIC单片机吧, RA2不是常量哦, 而是读取的引脚吧...

一语中的。我以为PD3就是端口。查资料得知在AVR宏定义中有#define PD3 3。受教了,明白了。多谢。

zw_7627 发表于 2014-11-17 14:15:28

本帖最后由 zw_7627 于 2014-11-17 14:16 编辑

发现key_press = GetKey()^ Key_Mask;只对相同电平输入有效,倘若有2路高入和2路低入同时存在,则无法判断。比如:RA1,RA2内部上拉,则PORTA= 000110;
而Key_Mask=110110; key_press = 110000;造成无法识别状态。

usm4glx 发表于 2015-10-13 08:26:29

不一定好用啊

GHmcu 发表于 2015-10-15 22:46:44

谢谢整理,值得学习。
页: [1]
查看完整版本: 写了一个独立按键 支持组合键、单键长按,连发功能的例子