寒假第一讲(按键)

第一章:按键系统

1.1 按键底层原理

  • 矩阵按键(先扫描行,再扫描列)
  • 独立按键(4个独立按键)

独立按键读取函数

unsigned char Key_Read() {
  unsigned char temp = 0;
  // 按优先级判断按键(P3.3优先级最高)
  if (P33 == 0) temp = 4; // 第4个按键按下
  if (P32 == 0) temp = 3; // 第3个按键按下
  if (P31 == 0) temp = 2; // 第2个按键按下
  if (P30 == 0) temp = 1; // 第1个按键按下
  return temp; // 返回0表示无按键,1-4表示按键编号
}

1.2 按键应用层(三行代码消抖)

Key_Val = Key_Read();
Key_Down = Key_Val & (Key_old ^ Key_Val);
Key_Up = ~Key_Val & (Key_old ^ Key_Val);
Key_old = Key_Val; // 保存当前状态供下次比较

状态变化表

Key_Old Key_Val 对应的按键过程 Key_Old ^ Key_Val Key_Down
0 0 未按下 0 0
0 4 按下过程中 4 4
4 4 按下稳定期间 0 0
4 0 抬起过程中 4 0

1.3 考点解析

考点1:模式切换

  • S4:定义为“界面”按键,按下S4切换温度显示、参数设置和DAC输出界面。
unsigned char Seg_show_mode; // 0:温度显示 1:参数设置 2:DAC输出

void Key_Proc() {
  static unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
  if (Key_Slow_Down) return;
  Key_Slow_Down = 1;
  Key_Val = Key_Read();
  Key_Down = Key_Val & (Key_Old ^ key_Val);
  Key_Up = ~Key_Val & (Key_Old ^ key_Val);
  Key_Old = Key_Val;
  if (Key_Down == 4)
    Seg_show_mode = (++Seg_show_mode) % 3; // 循环0-2
}

考点2:参数设置

  • S8:参数界面下,温度参数值加1。
  • S9:参数界面下,温度参数值减1;时间回显子界面下,长按S9超过2秒后松开,清除所有记录数据,触发次数重置为0。

考点3:参数保存

通过S4按键从参数设置界面退出时,需检查参数合理性(Tmax ≥ Tmin);若合理则生效,否则恢复原参数。

unsigned char Tmax_Control, Tmin_Control; // 参数设置值
unsigned char Tmax, Tmin; // 参数保存值

void Key_Proc() {
  static uchar Key_val, Key_Down, Key_Up, Key_Old;
  if (Key_Slow_Down) return;
  Key_Slow_Down = 1;
  Key_val = Key_Read();
  Key_Down = Key_val & (Key_Old ^ Key_val);
  Key_Up = ~Key_val & (Key_Old ^ Key_val);
  Key_Old = Key_val;
  if (Key_Down == 8) Tmax_Control++;
  if (Key_Down == 9) Tmin_Control++;
  if (Key_Down == 4) {
    if (Tmax_Control >= Tmin_Control) {
      Tmax = Tmax_Control;
      Tmin = Tmin_Control;
    } else {
      Tmax_Control = Tmax;
      Tmin_Control = Tmin;
    }
  }
}

1.4 按键多击

bit key_click_flag; // 按键触发标志
unsigned char time_100ms;
unsigned char key_click_count;

void Key_Proc() {
  static unsigned char Key_val, Key_Down, Key_Up, Key_Old;
  unsigned char i;
  if (Key_Slow_Down) return;
  Key_Slow_Down = 1;
  Key_val = Key_Read();
  Key_Down = Key_Val & (Key_Old ^ key_val);
  Key_Up = ~Key_Val & (Key_Old ^ key_val);
  Key_Old = Key_Val;
  if (Key_Down == 4) {
    Time_100ms = 0;
    Key_Click_Flag = 1;
    Key_Click_Count++;
  }
  if (Time_100ms >= 100) {
    switch (Key_Click_Count) {
      case 1: // 单击
        break;
      case 2: // 双击
        break;
      case 3: // 三击
        break;
    }
    Key_Click_Count = 0;
    Key_Click_Flag = 0;
    Time_100ms = 0;
  }
}

定时器支持

void Timer1_Isr(void) interrupt 3 {
  if (Key_Click_Flag) {
    if (++Time_100ms >= 100)
      Time_100ms = 101;
  } else {
    Time_100ms = 0;
  }
}