打印
[应用方案]

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

[复制链接]
203|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
a976209770|  楼主 | 2024-12-9 11:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

[i=s] 本帖最后由 a976209770 于 2024-12-9 11:57 编辑 [/i]<br /> <br />

[i=s] 本帖最后由 a976209770 于 2024-12-9 11:57 编辑 [/i]

前言

矩阵键盘是一种常见的输入设备,通常用于多按键场景,例如电子控制面板和嵌入式设备。通过利用行列交叉方式连接键盘按键,可以显著减少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[4][4] = {
    { '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[row][col];
            }
        }
    }

    // 未检测到按键
    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实现矩阵键盘的行列扫描方法,包括硬件配置、行列扫描逻辑、按键去抖处理等内容。该方案简单高效,适用于各类按键输入场景。通过进一步优化,可实现更多功能,如中断检测、多键支持等。

如果有相关问题或需要改进的建议,欢迎交流讨论!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

32

帖子

0

粉丝