51单片机-矩阵按键程序代码

一、先上代码

matrix_keyboard.c

cpp 复制代码
/*******************************************************************************
 * 矩阵键盘驱动程序
 * 
 * 硬件连接说明:
 * ============================================================================
 * 矩阵键盘引脚    单片机引脚      说明
 * ---------------------------------------------------------------------------
 * 行1-行4         P1.0-P1.3      输出,用于扫描
 * 列1-列4         P1.4-P1.7      输入,用于检测按键
 * ============================================================================
 * 
 * 键盘布局:
 * ============================================================================
 * 列1    列2    列3    列4
 * 行1:   1      2      3      上
 * 行2:   4      5      6      下  
 * 行3:   7      8      9      设置
 * 行4:   .      0      OK     清除
 * ============================================================================
 * 
 * 代码使用说明:
 * 1. 在主程序中包含头文件: #include "matrix_keyboard.h"
 * 2. 系统初始化时调用 keyboard_init() 初始化键盘
 * 3. 使用 keyboard_scan() 扫描键盘获取键值
 * 4. 使用 keyboard_get_key() 获取按键(带消抖)
 * 
 * 使用示例代码:
 * ============================================================================
 * #include "matrix_keyboard.h"
 * 
 * void main(void)
 * {
 *     u8 key;
 *     
 *     // 初始化键盘
 *     keyboard_init();
 *     
 *     while(1)
 *     {
 *         // 获取按键
 *         key = keyboard_get_key();
 *         
 *         if(key != KEY_NO_PRESS)
 *         {
 *             // 处理按键
 *             switch(key)
 *             {
 *                 case KEY_1:  // 处理数字1
 *                     break;
 *                 case KEY_UP: // 处理上键
 *                     break;
 *                 // ... 其他按键处理
 *             }
 *         }
 *         
 *         delay_ms(10);  // 适当延时
 *     }
 * }
 * ============================================================================
 * 
 * 注意事项:
 * 1. P1口需要配置为推挽输出模式
 * 2. 扫描频率不宜过高,建议10-20ms扫描一次
 * 3. 键值范围: 0-16 (0表示无按键)
 * 4. 支持按键消抖和按键释放检测
 ******************************************************************************/

#include "matrix_keyboard.h"
/*******************************************************************************
 * 函数名: delay_ms
 * 功能:   毫秒级延时(内部使用)
 * 参数:   ms - 延时的毫秒数
 * 返回值: 无
 * 说明:   该函数为内部函数,用于按键消抖
 ******************************************************************************/
static void delay_ms(int ms)
{
    int i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 110; j++);
}
/*******************************************************************************
 * 函数名: keyboard_init
 * 功能:   初始化矩阵键盘
 * 参数:   无
 * 返回值: 无
 * 说明:   配置键盘端口为初始状态
 *         设置P1口为高电平,准备扫描
 * 使用示例:
 *         keyboard_init();  // 初始化键盘
 ******************************************************************************/
void keyboard_init(void)
{
    KEYBOARD_PORT = 0xFF;  // 设置所有引脚为高电平
}

/*******************************************************************************
 * 函数名: keyboard_scan
 * 功能:   扫描矩阵键盘
 * 参数:   无
 * 返回值: u8 - 键值 (0表示无按键,1-16表示对应按键)
 * 说明:   逐行扫描检测按键,返回检测到的键值
 *         该函数不包含消抖,建议使用 keyboard_get_key()
 * 使用示例:
 *         u8 key = keyboard_scan();  // 扫描键盘
 *         if(key != KEY_NO_PRESS) {
 *             // 有按键按下
 *         }
 ******************************************************************************/
unsigned char keyboard_scan(void)
{
    unsigned char key_value = 0;
    unsigned char row, col;
    
    // 设置行线为输出,列线为输入
    KEYBOARD_PORT = COL_MASK;  // 1111 0000
    
    if((KEYBOARD_PORT & COL_MASK) != COL_MASK) {  // 有按键按下
        // 逐行扫描
        for(row = 0; row < 4; row++) {
            // 将当前行置低,其他行置高
            KEYBOARD_PORT = ~(1 << row) | COL_MASK;
            
            // 检查列
            if((KEYBOARD_PORT & 0x10) == 0) col = 0;  // 第1列
            else if((KEYBOARD_PORT & 0x20) == 0) col = 1;  // 第2列
            else if((KEYBOARD_PORT & 0x40) == 0) col = 2;  // 第3列
            else if((KEYBOARD_PORT & 0x80) == 0) col = 3;  // 第4列
            else continue;
            
            // 计算键值
            key_value = row * 4 + col + 1;  // 键值从1开始
            break;
        }
    }
    
    return key_value;
}

/*******************************************************************************
 * 函数名: keyboard_get_key
 * 功能:   获取按键值(带消抖)
 * 参数:   无
 * 返回值: u8 - 键值 (0表示无按键,1-16表示对应按键)
 * 说明:   包含按键消抖和按键释放检测
 *         只有在按键释放后才返回键值,避免重复触发
 * 使用示例:
 *         u8 key = keyboard_get_key();  // 获取按键
 *         if(key != KEY_NO_PRESS) {
 *             // 处理按键
 *         }
 ******************************************************************************/
unsigned char keyboard_get_key(void)
{
    unsigned char key_value = 0;
    
    // 扫描键盘
    key_value = keyboard_scan();
    
    if(key_value != KEY_NO_PRESS) {  // 有按键按下
        // 消抖延时
        delay_ms(10);
        
        // 再次扫描确认
        if(keyboard_scan() == key_value) {  // 确认按键按下
            // 等待按键释放
            while(keyboard_scan() != KEY_NO_PRESS);
            
            // 再次消抖
            delay_ms(10);
            
            return key_value;
        }
    }
    
    return KEY_NO_PRESS;
}

matrix_keyboard.h

cpp 复制代码
#ifndef __MATRIX_KEYBOARD_H__
#define __MATRIX_KEYBOARD_H__

#include <reg52.h>

//typedef unsigned char u8;
//typedef unsigned int u16;

// 矩阵键盘端口定义
#define KEYBOARD_PORT  P1
#define ROW_MASK       0x0F    // 行掩码 (P1.0-P1.3)
#define COL_MASK       0xF0    // 列掩码 (P1.4-P1.7)

// 键值定义
#define KEY_1          1       // 数字键1
#define KEY_2          2       // 数字键2
#define KEY_3          3       // 数字键3
#define KEY_UP         4       // 上键
#define KEY_4          5       // 数字键4
#define KEY_5          6       // 数字键5
#define KEY_6          7       // 数字键6
#define KEY_DOWN       8       // 下键
#define KEY_7          9       // 数字键7
#define KEY_8          10      // 数字键8
#define KEY_9          11      // 数字键9
#define KEY_SET        12      // 设置键
#define KEY_DOT        13      // 小数点
#define KEY_0          14      // 数字键0
#define KEY_OK         15      // 确认键
#define KEY_CLEAR      16      // 清除键

// 键盘状态
#define KEY_NO_PRESS   0       // 无按键按下

// 函数声明
void keyboard_init(void);
unsigned char keyboard_scan(void);
unsigned char keyboard_get_key(void);

#endif

二、硬件连接说明

模块和硬件的连接方式

Px0-》R1,

PX1->R2

PX2->R3

PX3->R4

PX4->C1

PX5->C2

PX6->C3

PX7->C4

如果自己画电路图

PX0开始接第一行

PX4开始接第一列

三、代码用法

调用函数eyboard_get_key(); 可返回按下的按键数值,16个按键从左上到右下分别为1-16,第一行1-4,按键具体功能据需要自定义了。比如提供的代码中宏定义

#define KEY_UP 4 // 上键

那么就是4号按键代表"上"

相关推荐
iCxhust5 小时前
将8088 BootLoader分拆烧写到8086 ROM中
stm32·单片机·嵌入式硬件·51单片机·微机原理
个微管理7 小时前
小红书新规深度拆解:从被封到破局,2026年矩阵号生存手册
大数据·人工智能·矩阵
互联科技报11 小时前
2026年第一季度短视频矩阵视频混剪头部工具市场动态深度解析
人工智能·矩阵·音视频
一晌小贪欢12 小时前
第3节:从表格到矩阵——NumPy 高级索引与维度变换实战
线性代数·矩阵·numpy
图码12 小时前
矩阵数据结构入门指南:声明、初始化与基本操作
运维·数据结构·线性代数·算法·矩阵
llilian_1614 小时前
晶振测量仪 晶振频率测试仪器的多领域应用解析 晶振频率测试仪器
功能测试·单片机·嵌入式硬件·测试工具·51单片机
我是大聪明.15 小时前
Attention机制的数学本质:从Softmax到FlashAttention的演进
线性代数·矩阵
智者知已应修善业15 小时前
【51单片机控制的交通信号灯三按键切换调节时分秒加减】2023-8-26
c++·经验分享·笔记·算法·51单片机
iCxhust2 天前
如何在汇编中修改CS:IP
汇编·单片机·嵌入式硬件·51单片机·微机原理