原创 一"雨"浇醒梦中人(含“零耗时消除键盘抖动”的C++键盘类源码)

2008-2-10 01:20 4102 7 7 分类: MCU/ 嵌入式

原帖讨论:  http://www.21icbbs.com/club/bbs/ShowAnnounce.asp?v=&ID=1715218



一"雨"浇醒梦中人
mood.gif hotpower 发表于 2005-6-28 14:22 AVR 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖


非常感谢John_Lee!!!!!!!!!!

特别特别感谢testcode!!!!!!!!!

一个"&"号断送了老农的"前程"...这个"雨"---"&"太妙了!!!

在MCU中应用C++确实有些"难为情",但它的风格实在令人难以忘怀...

我明白testcode肯定能够解决这个问题,虽然眼花但很"真情"..."相信您没错"...

两次的救助不知该如何答谢???

特别感谢上次的将整个类不初始化!!!
#define __noinit__ __attribute__ ((section (".noinit"))) //变量不初始化

__noinit__ RtcObj  Rtc;
__noinit__ LedObj  Led;
__noinit__ KeyObj  Key;
__noinit__ CtrlObj Ctrl;


只能以此程序向帮助我的网友们报答我的一片真心...

class KeyObj;//键盘模块

class KeyObj {
private:
  unsigned char KeyVal;//每20ms测试的键值(有1无0/有低无高)
  unsigned char KeyCount;//键盘计数器
  unsigned int KeyTest[8];//2.5mS压键计数器
public:
  KeyObj(void);
  void KeyInit(void);
  unsigned char GetKeyVal(void);//
  void KeyCommandExec(unsigned char);
  void Exec(void);
  void Key00(void);
  void Key01(void);
  void Key02(void);
  void Key03(void);
  void Key04(void);

  void Key10(void);
  void Key11(void);
  void Key12(void);
  void Key13(void);
  void Key14(void);

  void Key20(void);
  void Key21(void);
  void Key22(void);
  void Key23(void);
  void Key24(void);
};//键盘模块

__noinit__ KeyObj  Key;


//取串行键盘键值
inline
unsigned char KeyObj::GetKeyVal(void)
{
unsigned char KeyVal = 0;
  PORTC &= ~(1 << KeyCP);//脉冲锁存74HC165并行数据开始
  _NOP();//延时
  PORTC |=  (1 << KeyCP);//脉冲锁存74HC165并行数据结束
  for(int i = 8; i > 0; i --)
  {
    KeyVal <<= 1;
    PORTC &= ~(1 << KeyCLK);//发送读键脉冲
    _NOP();//延时
    if (!(PINC & (1 << KeyData))) KeyVal ++;//数据'1',有键压下为‘1’
    PORTC |=  (1 << KeyCLK);//发送读键脉冲
  }
  return KeyVal;//无键压下为0
}

//键扫描及运行(每2.5mS运行一次,实现“零耗时消除键盘抖动”)
inline
void KeyObj::Exec(void)//此程序套在定时中断中
{
static const unsigned char KeyTab[8] PROGMEM = {//只取当前键值表
  0b10000000,//键盘0
  0b01000000,//键盘1
  0b00100000,//键盘2
  0b00010000,//键盘3
  0b00001000,//键盘4
  0b00000100,//短接线0
  0b00000010,//短接线1
  0b00000001 //短接线2
};
  KeyCount &= 0x07;//只有8个键
  KeyVal = GetKeyVal();//取所有键位值
  if (KeyVal & pgm_read_byte(&KeyTab[KeyCount])) {//有键压下(每次只取1键以实现“零耗时消除键盘抖动”)
    if (KeyTest[KeyCount] < 1200) {//1200*2.5mS=3S//压键长短判别
      KeyTest[KeyCount] ++;//计数每20mS键盘压键的次数(选2较好些)
      if (KeyTest[KeyCount] == 2) {//键刚压下//短压键
        KeyCommandExec(1);//短压键事件处理(1)
      }
    }
    else {//长压键 2.5mS*1200=3S
      KeyTest[KeyCount] = 2;//再压3S继续执行下一次长压键
      KeyCommandExec(2);//长压键3S事件处理(2)
    }
  }
  else {//无键压下
    if (KeyTest[KeyCount] >= 2) {//键释放
      KeyCommandExec(0);//键释放事件处理(0)
    }
    else {//无键压下或干扰
    }
    KeyTest[KeyCount] = 0;//清除压键计数器
  }
  KeyCount ++;//为下次扫描做准备
  KeyCount &= 0x07;//只有8个键
}


typedef prog_void (KeyObj::* PFV)(void);
void KeyObj::KeyCommandExec(unsigned char mode)
{
static const PFV KeyCommandTab[3][5] = {//键盘事件处理表
  {&KeyObj::Key00, &KeyObj::Key01, &KeyObj::Key02, &KeyObj::Key03, &KeyObj::Key04}, //键释放事件处理
  {&KeyObj::Key10, &KeyObj::Key11, &KeyObj::Key12, &KeyObj::Key13, &KeyObj::Key14}, //压键事件处理
  {&KeyObj::Key20, &KeyObj::Key21, &KeyObj::Key22, &KeyObj::Key23, &KeyObj::Key24}  //长压键事件处理
};
  KeyCount &= 0x07;//取键盘序号
  if (KeyCount <= 4) {//只有5个键,KeyCount>=5为3个短接线
    (::Key.*KeyCommandTab[(int)mode][(int)KeyCount])();//运行KeyX0()~KeyX4()
  }
}

/*------------------------
     键释放事件处理
------------------------*/
void KeyObj::Key00(void)
{
}

void KeyObj::Key01(void)
{
}

void KeyObj::Key02(void)
{
}

void KeyObj::Key03(void)
{
}

void KeyObj::Key04(void)
{
}

/*------------------------
     压键事件处理
------------------------*/
void KeyObj::Key10(void)
{
}

void KeyObj::Key11(void)
{
}

void KeyObj::Key12(void)
{
}

void KeyObj::Key13(void)
{
}

void KeyObj::Key14(void)
{
}

/*------------------------
     长压键事件处理
------------------------*/
void KeyObj::Key20(void)
{
}

void KeyObj::Key21(void)
{
}

void KeyObj::Key22(void)
{
}

void KeyObj::Key23(void)
{
}

void KeyObj::Key24(void)
{
}
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /3 下一条