蓝桥杯单片机比赛矩阵按键模块(原理函数代码详解)

文章详细介绍了矩阵按键的工作原理,包括独立按键的内部结构和抖动问题,以及如何通过编程进行消抖处理。在STC15F2K60S2单片机上,通过扫描矩阵键盘的行列来判断按键状态,并给出了控制LED灯亮灭的示例代码。此外,文章还提供了矩阵按键函数的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原件介绍

矩阵按键是由16个独立按键组成的,所以它的工作原理与独立按键相同。

独立按键的工作原理就是将按键的信号转换成电脑可以理解的信号,并且传输给处理器

独立按键的内部结构是一个弹性贴片,在按下松手时会有抖动,抖动的时间大概有20ms,如果不进行处理,很有可能松手的时候会出现抖动误判。所以我们在写按键程序时要加上延时消抖

                 内部结构图                                                        按键抖动波形图
 

原理图

在写代码之前还是和之前一样,先看原理图。

       当J5的跳线帽插在1,2两个插针上时,S7、S6、S5、S4四个独立按键与P44口相连,使用的是矩阵键盘模式。不难看出矩阵键盘的第一、二、三、四列分别连接在P44、P42、P35、P34口上,第一、二、三、四行分别连接在P30、P31、P32、P33口上。

这时我们应该如何判断一个按键是否被按下呢?其实我们可以类比成坐标的形式,对行列同时进行判断,例如:P44==0将第一列置于低电平,如果将S7按键按下,则P30口导通,也是低电平,因此可以判断出是哪个按键按下,以此类推。

代码解析

1、矩阵键盘控制LED灯亮灭

//矩阵键盘控制LED灯亮灭
#include <STC15F2K60S2.H>

unsigned char num;

void Delayms(unsigned int ms);

void main(void)
{
    P2=0X80;P0=0XFF;P2=0XA0;P0=0X00;     //初始化,在后面会专门出一期讲初始化函数
    while(1)
    {
        unsigned char temp;
        P44=0;P42=1;P3=0X7F;    //使用第一列按键
        temp=P3;                //将P3的值赋给中间变量temp
        temp=temp&0X0F;         //0111 1111 & 0000 1111 -> 0000 1111 判断第四位是否发生变化
        if(temp!=0X0F)          //如果发生变化,则第一列有按键按下
        {
            Delayms(5);         //延时消抖
            temp=P3;            //重复赋值、判断
            temp=temp&0X0F;
            if(temp!=0X0F)
            {
                temp=P3;        //在赋值判断时temp的值发生了变化,所以要重新将P3的值赋给temp
                switch(temp)
                {
                    case 0x7e: num=1; break;        //0111 1110 一行一列按下,赋值num=1
                    case 0x7d: num=2; break;        //0111 1101 一行二列按下,赋值num=2
                    case 0x7b: num=3; break;        //0111 1011 一行三列按下,赋值num=3
                    case 0x77: num=4; break;        //0111 0111 一行四列按下,赋值num=4       
                }
            }
            while(temp!=0X0F)          //松手检测,如果有按键按下
            {
                temp=P3;               //则一直进行赋值判断,直至松手
                temp=temp&0X0F;
            }
        }
        
        if(num==1)           //按键控制LED灯亮灭
        {   P2=0X80;P0=0XFF;
            P00=0;
        }
        if(num==2)
        {   P2=0X80;P0=0XFF;
            P00=1;
        }
    }
}

void Delayms(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
        for(j=845;j>0;j--);
}

2、矩阵按键函数的使用

//矩阵按键函数的使用
#include <STC15F2K60S2.H>

unsigned char num;          //键码值

void Delayms(unsigned int ms); //函数声明
void Key16(void);

void main(void)
{                           //初始化
    P2=0X80;P0=0XFF;
    P2=0XA0;P0=0X00;
    while(1)
    {
       Key16();             //调用矩阵按键函数
       if(num==1)           //当第一个按键按下时
        {
            P2=0X80;P0=0XFF;    //打开LED573锁存器,关闭所以LED灯   初始化
            P00=0;              //点亮第一个LED灯
        }
    }
}

void Key16(void)          //矩阵键盘函数(按列扫描)
{
    unsigned char temp;
    //第一列扫描
    P44=0;P42=1;P3=0X7F;    //0111 1111 高四位是列,第四位是行
    temp=P3;                //将P3的值赋给中间变量temp
    temp=temp&0X0F;         //0111 1111 & 0000 1111 -> 0000 1111 判断第四位是否发生变化
    if(temp!=0X0F)          //如果发生变化,则第一列有按键按下
    {
        Delayms(5);         //延时消抖
        temp=P3;            //重复赋值、判断
        temp=temp&0X0F;
        if(temp!=0X0F)
        {
            temp=P3;        //在赋值判断时temp的值发生了变化,所以要重新将P3的值赋给temp
            switch(temp)
            {
                case 0x7e: num=1; break;        //0111 1110 一行一列按下,赋值num=1
                case 0x7d: num=2; break;        //0111 1101 一行二列按下,赋值num=2
                case 0x7b: num=3; break;        //0111 1011 一行三列按下,赋值num=3
                case 0x77: num=4; break;        //0111 0111 一行四列按下,赋值num=4       
            }
        }
        while(temp!=0X0F)          //松手检测,如果有按键按下
        {
            temp=P3;               //则一直进行赋值判断,直至松手
            temp=temp&0X0F;
        }
    }
    //第二列扫描,逻辑原理与第一列相似
    P44=1;P42=0;P3=0XBF;    //0111 1110
    temp=P3;
    temp=temp&0X0F;
    if(temp!=0X0F)
    {
        Delayms(5);
        temp=P3;
        temp=temp&0X0F;
        if(temp!=0X0F)
        {
            temp=P3;
            switch(temp)
            {
                case 0xbe: num=5; break;
                case 0xbd: num=6; break;
                case 0xbb: num=7; break;
                case 0xb7: num=8; break;               
            }
        }
        while(temp!=0X0F)
        {
            temp=P3;
            temp=temp&0X0F;
        }
    }
    //第三列扫描
    P44=1;P42=1;P3=0XDF;    //0111 1110
    temp=P3;
    temp=temp&0X0F;
    if(temp!=0X0F)
    {
        Delayms(5);
        temp=P3;
        temp=temp&0X0F;
        if(temp!=0X0F)
        {
            temp=P3;
            switch(temp)
            {
                case 0xde: num=9; break;
                case 0xdd: num=10; break;
                case 0xdb: num=11; break;
                case 0xd7: num=12; break;               
            }
        }
        while(temp!=0X0F)
        {
            temp=P3;
            temp=temp&0X0F;
        }
    }
    //第四列扫描
    P44=1;P42=1;P3=0XEF;    //0111 1110
    temp=P3;
    temp=temp&0X0F;
    if(temp!=0X0F)
    {
        Delayms(5);
        temp=P3;
        temp=temp&0X0F;
        if(temp!=0X0F)
        {
            temp=P3;
            switch(temp)
            {
                case 0xee: num=13; break;
                case 0xed: num=14; break;
                case 0xeb: num=15; break;
                case 0xe7: num=16; break;               
            }
        }
        while(temp!=0X0F)
        {
            temp=P3;
            temp=temp&0X0F;
        }
    }
}

void Delayms(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
        for(j=845;j>0;j--);
}

以上就是我对矩阵按键模块的全部理解,如有不对之处,还希望大家留言指正。有什么好的建议也可以留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值