普中开源电子分享网

 找回密码
 立即注册
搜索
查看: 4037|回复: 4

关于AT89C51矩阵键盘学习的两个问题

 关闭 [复制链接]

3

主题

6

帖子

27

积分

新手上路

Rank: 1

积分
27
发表于 2017-6-18 10:16:51 | 显示全部楼层 |阅读模式
刚学单片机,C语言还可以。现在遇到两个问题:1、视频里矩阵键盘逐行扫描法说是高四位轮流输出低电平,判断第四位哪路输出低电平即为哪个按键按下。
我的问题是:为什么要高四位轮流输出低电平,而不是高四位轮流输出高电平?两种程序我都编了,只有第一种可行。

2、视频里采用静态数码管来显示数字0-F,我想结合动态数码管来显示0-15的数字,如图。最终效果是正确的。但是为什么我按下键盘时,会显示两个数字,松开键盘时,前面一位消失了,恢复正常状态?
附上我的程序:
#include "reg52.h"
#include "intrins.h"


typedef unsigned char u8;
typedef unsigned int u16;
typedef double  u32;

#define MatrixKey  P0
#define BitChoose  P3
#define DynamicLed P1

void delay(u16 i)
{
        while(i--);
}
u8 Num[10] = {
        0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F               
};                                                                                                           //0-9数字的16进制表示, 共阴
u8 RowKey[4] = {0x0E, 0x0D, 0x0B, 0x07};                        //
u8 ColumnKey[4] = {0xE0, 0xD0, 0xB0, 0x70};
void ShowNum(u8 i, u8 j)                                                        //根据行列显示数码管数字
{
        u8 k;
        k = (i - 1) * 4 + j;
        if(k < 10)
        {
                 DynamicLed = Num[k];
                 BitChoose = 0x07;                                                  //0000 0111
        }
        else if(k >= 10 && k < 16)
        {
                  DynamicLed = Num[1];
                  BitChoose = 0x06;
                  delay(100);
                  DynamicLed = Num[k - 10];
                  BitChoose = 0x07;
                  delay(100);
        }
        else
        {
                DynamicLed = Num[0];
                BitChoose = 0x07;
        }
}
                                                                        
u8 RowNum, ColumnNum;                                                                                                                 //定义全局变量
sbit Led = P3^0;

void main()
{
        RowNum = 0;                                                                                                //初始化行列数
        ColumnNum = 0;
       
        while(1)
        {
                u8 MatchKey;
                u8 a;
                u8 i, j;
                //MatrixKey = 0xFF;                                                                        //初始化P0                                                                               
                                for(i = 0; i < 4; i++)                                                 //从第一行循环往下找
                                {
                                        MatrixKey = RowKey[i] + 0xF0;
                                        MatchKey = RowKey[i];
                                        for(j = 0; j < 4; j++)
                                        {         
                                                 if(MatrixKey == MatchKey + ColumnKey[j])                                   //MatrixKey为真实管脚输出值,MatchKey为行索引, ColumnKey为列索引
                                                {
                                                        delay(1000);                                                                                   //消抖
                                                        Led = 0;                                                                               
                                                        if(MatrixKey == MatchKey + ColumnKey[j])
                                                        {
                                                                 RowNum = i + 1;
                                                                ColumnNum = j + 1;
                                                                while(a < 50 && MatrixKey == MatchKey + ColumnKey[j])                 //判断是否松开,或500ms后自动松开
                                                                {
                                                                        delay(1000);
                                                                        a++;
                                                                }
                                                                break;
                                                        }
                                                 }
                                                       
                                        }       
                                }
                                ShowNum(RowNum, ColumnNum);
        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

0

主题

29

帖子

322

积分

中级会员

Rank: 3Rank: 3

积分
322
发表于 2017-6-18 11:02:09 | 显示全部楼层
为什么要高四位轮流输出低电平,而不是高四位轮流输出高电平?
#define MatrixKey  P0         
//MatrixKey = 0xFF;           //初始化P0  
你的P0串口都初始化为高电平了,
只有高四位轮流输出低电平,低四位端口才能检到有没有端口被拉低为低电平了。
回复 支持 反对

使用道具 举报

3

主题

6

帖子

27

积分

新手上路

Rank: 1

积分
27
 楼主| 发表于 2017-6-18 17:27:40 | 显示全部楼层
在路上 发表于 2017-6-18 11:02
为什么要高四位轮流输出低电平,而不是高四位轮流输出高电平?
#define MatrixKey  P0         
//Matrix ...

我开始是初始化为低电平的,因为那样不行,我才按照教程上的初始化为高电平来做的。
回复 支持 反对

使用道具 举报

20

主题

1344

帖子

8385

积分

论坛元老

Rank: 8Rank: 8

积分
8385
发表于 2017-6-19 09:20:46 | 显示全部楼层
你的第一个问题,是程序的问题。
你看程序:
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
        {
                case(0X07):        KeyValue=0;break;
                case(0X0b):        KeyValue=4;break;
                case(0X0d): KeyValue=8;break;
                case(0X0e):        KeyValue=12;break;
        }

你想用高电平去检测,那么,这个程序里的所有数据(红色)都要取反,,另一半程序同时理。你可以试试
回复 支持 反对

使用道具 举报

3

主题

6

帖子

27

积分

新手上路

Rank: 1

积分
27
 楼主| 发表于 2017-6-19 23:29:57 | 显示全部楼层
HC6800-ES-V2.0 发表于 2017-6-19 09:20
你的第一个问题,是程序的问题。
你看程序:
//测试列

你这个办法是视频教程里的第二种方法,行列扫描法,我想采用的是第一种方法逐行扫描法。逐行扫描法描述是初始化高四位为高电平,然后高四位依次输出低电平,低四位检测到低电平即可确认位置。这个我已经做成了,我上述程序没有问题的。但是我想试一下高四位初始化为低电平,然后高四位轮流输出高电平,低四位检测到高电平即可确定位置,和教程的电平设置反一下就不行了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

Archiver|手机版|小黑屋|普中开源电子分享网 粤ICP备16123577号-2

GMT+8, 2024-5-1 03:35 , Processed in 0.089429 second(s), 31 queries .

Powered by 论坛搭建 X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表