a976209770 发表于 2024-12-9 11:51

基于APM32实现矩阵键盘的行列扫描

本帖最后由 a976209770 于 2024-12-9 11:57 编辑

本帖最后由 a976209770 于 2024-12-9 11:57 编辑

## **前言**

矩阵键盘是一种常见的输入设备,通常用于多按键场景,例如电子控制面板和嵌入式设备。通过利用行列交叉方式连接键盘按键,可以显著减少I/O端口的使用。本文基于APM32微控制器实现矩阵键盘的行列扫描,详细介绍其配置与实现。

---

## **1. 矩阵键盘的基本原理**

1. **矩阵连接**:按键以行列形式连接,例如4行×4列键盘共使用8个I/O引脚,可支持16个按键。
2. **行列扫描**:通过逐行设置电平并逐列读取,判断当前哪个按键被按下。

### **硬件连接**

* 行线连接到GPIO端口的输出。
* 列线连接到GPIO端口的输入。

---

## **2. 软件设计**

### **2.1 硬件配置**

#### **GPIO初始化**

1. 将行设置为推挽输出。
2. 将列设置为上拉输入。
3. 使用GPIO库配置端口和引脚。

#### **GPIO配置代码**

```
#include "apm32f4xx_gpio.h"

#define ROW_PORT GPIOA
#define COL_PORT GPIOB

#define ROW_PINS (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
#define COL_PINS (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7)

void MatrixKeyboard_Init(void)
{
    GPIO_Config_T gpioConfig;

    // 配置行为输出
    gpioConfig.pin = ROW_PINS;
    gpioConfig.mode = GPIO_MODE_OUT;
    gpioConfig.speed = GPIO_SPEED_50MHz;
    gpioConfig.otype = GPIO_OTYPE_PP;
    gpioConfig.pupd = GPIO_PUPD_NOPULL;
    GPIO_Config(ROW_PORT, &gpioConfig);

    // 配置列为输入
    gpioConfig.pin = COL_PINS;
    gpioConfig.mode = GPIO_MODE_IN;
    gpioConfig.speed = GPIO_SPEED_50MHz;
    gpioConfig.pupd = GPIO_PUPD_UP; // 上拉输入
    GPIO_Config(COL_PORT, &gpioConfig);
}

```

### **2.2 行列扫描逻辑**

#### **按键检测原理**

1. 将某一行拉低,其他行拉高。
2. 读取列引脚状态。
3. 如果某列为低电平,说明对应行列按键被按下。

#### **扫描代码**

```
#include "apm32f4xx_gpio.h"

// 定义行列映射
uint8_t KeyMap = {
    { '1', '2', '3', 'A' },
    { '4', '5', '6', 'B' },
    { '7', '8', '9', 'C' },
    { '*', '0', '#', 'D' }
};

uint8_t MatrixKeyboard_Scan(void)
{
    for (uint8_t row = 0; row < 4; row++)
    {
      // 设置当前行低电平,其他行高电平
      GPIO_WriteOutputPort(ROW_PORT, ~(1 << row) & ROW_PINS);

      // 延时,确保电平稳定
      for (volatile int i = 0; i < 1000; i++);

      // 读取列状态
      uint16_t colState = GPIO_ReadInputPort(COL_PORT) & COL_PINS;

      for (uint8_t col = 0; col < 4; col++)
      {
            // 检测列是否为低电平
            if ((colState & (1 << (col + 4))) == 0)
            {
                // 返回按键值
                return KeyMap;
            }
      }
    }

    // 未检测到按键
    return 0;
}

```

### **2.3 处理多键与去抖**

#### **去抖逻辑**

在矩阵键盘中,按键可能因机械抖动产生多次触发,需要加入延时和状态确认机制。

```
uint8_t MatrixKeyboard_GetKey(void)
{
    uint8_t key = 0;
    static uint8_t lastKey = 0;

    key = MatrixKeyboard_Scan();

    if (key != 0 && key == lastKey)
    {
      // 延时去抖
      for (volatile int i = 0; i < 10000; i++);
      return key;
    }

    lastKey = key;
    return 0;
}

```

## **3. 应用场景**

### **3.1 实现多功能按键**

* 每个按键可以对应不同的功能,通过检测返回值触发事件。
* 示例:'A' 控制启动,'B' 控制停止。

```
void ProcessKey(uint8_t key)
{
    switch (key)
    {
      case 'A':
            StartProcess();
            break;
      case 'B':
            StopProcess();
            break;
      // 其他按键功能
      default:
            break;
    }
}

```

---

## **4. 优化与特点**

### **4.1 优化方向**

1. **支持中断检测:** 配置列引脚为中断输入,按键按下时触发中断,减少扫描资源占用。
2. **动态按键定义:** 使用外部配置文件动态定义键值映射,增强灵活性。
3. **支持多键检测:** 增加寄存状态,支持同时多键按下的情况。

### **4.2 特点**

1. **I/O占用少:** 使用8个引脚即可支持16个按键。
2. **逻辑简单:** 基于GPIO的行列扫描,易于移植。
3. **稳定可靠:** 加入去抖逻辑,保证按键检测的准确性。

---

## **5. 总结**

本文详细介绍了基于APM32实现矩阵键盘的行列扫描方法,包括硬件配置、行列扫描逻辑、按键去抖处理等内容。该方案简单高效,适用于各类按键输入场景。通过进一步优化,可实现更多功能,如中断检测、多键支持等。

如果有相关问题或需要改进的建议,欢迎交流讨论!
页: [1]
查看完整版本: 基于APM32实现矩阵键盘的行列扫描