通过AT89C51单片机(开发板)实现矩阵键盘与数码管显示

51单片机实现矩阵键盘与数码管显示

一、目的

通过AT89C51单片机实现数码管显示按下的按键值0~F,掌握矩阵键盘接口电路设计及编程应用。

二、矩阵键盘工作原理

 1. 矩阵键盘结构

- 行列扫描法:将按键排列成N行×M列的矩阵

- 节省I/O口:4×4键盘只需8个I/O口,而独立键盘需要16个

- 工作方式:通过行线和列线的交叉点判断按键状态

2. 键盘扫描流程

1. 判断是否有按键按下:将所有行线置为低电平,检测列线状态

2. 延时消抖:确认按键按下后延时20ms,消除机械抖动

3. 识别按键位置:逐行扫描,确定具体按下的按键

4. 等待按键释放:检测按键释放后再进行处理

三、硬件设计

 1. 电路连接图

矩阵键盘(4×4)   AT89C51单片机

行线(R0-R3)   →  P1.0-P1.3

列线(C0-C3)   →  P1.4-P1.7

数码管段选信号 →  P0.0-P0.7

数码管位选信号 →  P2.0-P2.7

2. Proteus电路设计

1. 添加AT89C51单片机

2. 添加4×4矩阵键盘

3. 添加共阴极数码管

4. 添加限流电阻

5. 连接晶振电路(12MHz)和复位电路

设计原理图:

四、软件设计

1. 矩阵键盘扫描程序

#include <reg52.h>

#include <intrins.h>

typedef unsigned char uchar;

typedef unsigned int uint;

// 数码管段选端口

#define SEG_PORT P0

// 矩阵键盘端口

#define KEY_PORT P1

// 共阴极数码管0-F的段码表

uchar code seg_table[] = {

    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,

    0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71

};

// 延时函数

void Delay_ms(uint ms)

{

    uint i, j;

    for(i = 0; i < ms; i++)

        for(j = 0; j < 110; j++);

}

// 矩阵键盘扫描函数,返回键值(0-15)

uchar KeyScan()

{

    uchar key_value = 0xFF;  // 初始键值设为0xFF表示无按键按下

    uchar temp;

    // 第一步:判断是否有按键按下

    KEY_PORT = 0xF0;  // 行线置高,列线置低

    temp = KEY_PORT;  // 读取按键状态

    temp &= 0xF0;     // 屏蔽低4位(行线)

    if(temp != 0xF0)  // 如果有按键按下

    {

        Delay_ms(20);  // 延时消抖

        temp = KEY_PORT;

        temp &= 0xF0;

        if(temp != 0xF0)  // 再次确认有按键按下

        {

            // 第二步:逐行扫描确定按键位置

            // 扫描第一行

            KEY_PORT = 0xFE;  // 0b11111110

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 0;  // 第一行第一列

                if(temp == 0xD0) key_value = 1;  // 第一行第二列

                if(temp == 0xB0) key_value = 2;  // 第一行第三列

                if(temp == 0x70) key_value = 3;  // 第一行第四列

            }

            // 扫描第二行

            KEY_PORT = 0xFD;  // 0b11111101

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 4;  // 第二行第一列

                if(temp == 0xD0) key_value = 5;  // 第二行第二列

                if(temp == 0xB0) key_value = 6;  // 第二行第三列

                if(temp == 0x70) key_value = 7;  // 第二行第四列

            }

            // 扫描第三行

            KEY_PORT = 0xFB;  // 0b11111011

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 8;  // 第三行第一列

                if(temp == 0xD0) key_value = 9;  // 第三行第二列

                if(temp == 0xB0) key_value = 10; // 第三行第三列

                if(temp == 0x70) key_value = 11; // 第三行第四列

            }

            // 扫描第四行

            KEY_PORT = 0xF7;  // 0b11110111

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 12; // 第四行第一列

                if(temp == 0xD0) key_value = 13; // 第四行第二列

                if(temp == 0xB0) key_value = 14; // 第四行第三列

                if(temp == 0x70) key_value = 15; // 第四行第四列

            }

            // 等待按键释放

            while((KEY_PORT & 0xF0) != 0xF0);

            Delay_ms(20);  // 释放后延时消抖

        }

    }

    return key_value;

}

// 显示函数

void Display(uchar num)

{

    SEG_PORT = seg_table[num];  // 输出段码

}

// 主函数

void main()

{

    uchar key;

    while(1)

    {

        key = KeyScan();  // 扫描键盘

        if(key != 0xFF)   // 如果有按键按下

        {

            Display(key); // 显示键值

        }

    }

}

 2. 键盘编码说明

```

矩阵键盘布局及编码:

    C0  C1  C2  C3

R0  0   1   2   3

R1  4   5   6   7

R2  8   9   A   B

R3  C   D   E   F

五、步骤

 1. Proteus电路设计

1. 新建Proteus项目

2. 添加AT89C51单片机

3. 添加4×4矩阵键盘

4. 添加共阴极数码管

5. 添加必要的电阻和电源

6. 按照电路连接图进行连线

 2. 软件编程

1. 在Keil uVision中创建新项目

2. 编写键盘扫描和数码管显示程序

3. 编译程序,生成HEX文件

 3. 仿真测试

1. 在Proteus中加载HEX文件

2. 设置晶振频率为12MHz

3. 运行仿真

4. 点击矩阵键盘上的按键,观察数码管显示结果

六、实验结果与分析

1. 功能验证

- 按下矩阵键盘上的按键,数码管显示对应数字0-9或字母A-F

- 按键识别准确,无误判现象

- 消抖处理有效,无连击现象

 2. 技术要点

- 行列扫描法:通过逐行扫描和列线检测确定按键位置

- 按键消抖:软件延时20ms消除机械抖动

- 共阴极数码管:高电平点亮对应段,通过段码表转换数字

 3. 常见问题及解决方法

- 按键无响应:检查连接线是否正确,I/O口设置是否匹配

- 显示乱码:检查段码表是否正确,共阴/共阳选择是否匹配

- 按键误判:增加消抖延时,或改进扫描算法

七、总结与拓展

1. 总结

通过本次实验,需要掌握:

- 矩阵键盘的工作原理和接口设计

- 行列扫描法识别按键的方法

- 键盘消抖处理技术

- 数码管显示数字和字母的实现方法

2. 拓展应用

矩阵键盘可应用于:

- 电子密码锁

- 简易计算器

- 电子时钟调整界面

- 智能家居控制面板

 3. 改进方向

- 增加按键音效反馈

- 实现组合键功能

- 优化键盘扫描算法,提高响应速度

- 添加按键长按功能

八、附录

 1. 完整代码

#include <reg52.h>

#include <intrins.h>

typedef unsigned char uchar;

typedef unsigned int uint;

// 数码管段选端口

#define SEG_PORT P0

// 矩阵键盘端口

#define KEY_PORT P1

// 共阴极数码管0-F的段码表

uchar code seg_table[] = {

    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,

    0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71

};

// 延时函数

void Delay_ms(uint ms)

{

    uint i, j;

    for(i = 0; i < ms; i++)

        for(j = 0; j < 110; j++);

}

// 矩阵键盘扫描函数,返回键值(0-15)

uchar KeyScan()

{

    uchar key_value = 0xFF;  // 初始键值设为0xFF表示无按键按下

    uchar temp;

    // 第一步:判断是否有按键按下

    KEY_PORT = 0xF0;  // 行线置高,列线置低

    temp = KEY_PORT;  // 读取按键状态

    temp &= 0xF0;     // 屏蔽低4位(行线)

    if(temp != 0xF0)  // 如果有按键按下

    {

        Delay_ms(20);  // 延时消抖

        temp = KEY_PORT;

        temp &= 0xF0;

        if(temp != 0xF0)  // 再次确认有按键按下

        {

            // 第二步:逐行扫描确定按键位置

            // 扫描第一行

            KEY_PORT = 0xFE;  // 0b11111110

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 0;  // 第一行第一列

                if(temp == 0xD0) key_value = 1;  // 第一行第二列

                if(temp == 0xB0) key_value = 2;  // 第一行第三列

                if(temp == 0x70) key_value = 3;  // 第一行第四列

            }

            // 扫描第二行

            KEY_PORT = 0xFD;  // 0b11111101

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 4;  // 第二行第一列

                if(temp == 0xD0) key_value = 5;  // 第二行第二列

                if(temp == 0xB0) key_value = 6;  // 第二行第三列

                if(temp == 0x70) key_value = 7;  // 第二行第四列

            }

            // 扫描第三行

            KEY_PORT = 0xFB;  // 0b11111011

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 8;  // 第三行第一列

                if(temp == 0xD0) key_value = 9;  // 第三行第二列

                if(temp == 0xB0) key_value = 10; // 第三行第三列

                if(temp == 0x70) key_value = 11; // 第三行第四列

            }         

            // 扫描第四行

            KEY_PORT = 0xF7;  // 0b11110111

            temp = KEY_PORT;

            temp &= 0xF0;

            if(temp != 0xF0)

            {

                if(temp == 0xE0) key_value = 12; // 第四行第一列

                if(temp == 0xD0) key_value = 13; // 第四行第二列

                if(temp == 0xB0) key_value = 14; // 第四行第三列

                if(temp == 0x70) key_value = 15; // 第四行第四列

            }           

            // 等待按键释放

            while((KEY_PORT & 0xF0) != 0xF0);

            Delay_ms(20);  // 释放后延时消抖

        }

    }   

    return key_value;

}

// 显示函数

void Display(uchar num)

{

    SEG_PORT = seg_table[num];  // 输出段码

}

// 主函数

void main()

{

    uchar key;   

    while(1)

    {

        key = KeyScan();  // 扫描键盘

        if(key != 0xFF)   // 如果有按键按下

        {

            Display(key); // 显示键值

        }

    }

}

希望这篇博客对你理解51单片机矩阵键盘和数码管显示有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值