c - 如何使用微 Controller 检测键盘矩阵中开关的释放?

标签 c arduino embedded microcontroller microchip

我想检测按键矩阵中开关的释放。考虑 4*4 键矩阵,微 Controller 的扫描可以轻松完成以检测按键 PRESS。但是,我还想在释放发生时检测它们。 有没有比仅对未按下的状态更改中断进行另一次扫描更有效的方法?

最佳答案

矩阵键盘扫描不需要任何中断。您应该创建将定期调用的扫描函数。最好的方法是将每个键存储为某个变量中的一个位 - 您有 4x4 键盘,因此 uint16_t 将完全适合。 XOR 运算符非常适合 key 更改检测。另外不要忘记实现一些关键的去抖功能。

我建议遵循“伪”代码或类似的代码(我希望其中没有错误):

#define ROW_COUNT         4
#define COL_COUNT         4
#define DEBOUNCE_TIMEOUT  10   // In milliseconds

typedef uint16_t KeyState;

// This function returns current keyboard state and
// fills upKeys with keys that were pressed and downKeys with keys that were released
// It expects that key down is logic H, up is logic L
KeyState KeyboardState(KeyState* upKeys, KeyState* downKeys)
{
  static KeyState lastState = 0;
  static KeyState lastValidState = 0;
  static Timestamp lastTimestamp = 0;
  KeyState currentState = 0;
  uint8_t x, y;

  // Set defaults
  if (upKeys)
    *upKeys = 0;
  if (downKeys)
    *downKeys = 0;

  for(y = 0; y < ROW_COUNT; y++)
  {
    // Set appropriate row pin to H
    SetRowPinH(y);
    // Just to be sure that any parasitic capacitance gets charged
    SleepMicro(10);
    for(x = 0; x < COL_COUNT; x++)
    {
      // Check key pressed
      if (IsColPinSet(x))
        currentState |= 1 << ((y * COL_COUNT) + x);
    }
    // And don't forget to set row pin back to L
    SetRowPinL(y);
  }

  // Now lets do debouncing - this is important for good functionality
  // Matrix state should not change for some time to accept result
  if (lastState == currentState)
  {
    // Check if time has passed
    if ((TimestampNowMilli() - lastTimestampMilli) >= DEBOUNCE_TIMEOUT)
    {
      // Let's detect up/down changes first - it's easy, just use XOR for change detection
      if (upKeys)
        *upKeys = currentState & (lastValidState ^ currentState);
      if (downKeys)
        *downKeys = (~currentState) & (lastValidState ^ currentState);
      lastValidState = currentState;
    }
  }
  else
  {
    // Current state differs from previous - reset timer
    lastTimestampMilli = TimestampNowMilli();
  }
  lastState = currentState;

  return lastValidState;
}

int main()
{
  KeyState upKeys;
  KeyState downKeys;
  KeyState currentKeys;
  while(1)
  {
    currentKeys = KeyboardState(&upKeys, &downKeys);
    if (upKeys & 0x0001)
      printf("Key 1 pressed\n");
    if (downKeys & 0x0001)
      printf("Key 1 released\n");
  }
}

关于c - 如何使用微 Controller 检测键盘矩阵中开关的释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59472548/

相关文章:

c - 指针和写访问冲突

objective-c - 如何将变量的值与#define 进行比较

c - 快速排序功能不起作用(在 c 中)

c - 多个线程访问一个变量

c++ - Arduino 从 'char' 到 'char*' 的无效转换

c - 我的引导加载程序无法在 stm32 上启动我的新程序

java - 安卓 & 蓝牙 & Arduino

Python:GUI - 绘图,从实时 GUI 中的像素读取

c - 使用 fread 从 Matlab 读取所有字符到嵌入式设备

hardware - 如何确定嵌入式系统应用程序/软件的系统要求