单片机学习小组
直播中

HTSX

9年用户 786经验值
擅长:可编程逻辑
私信 关注

矩阵按键的原理是什么?有哪几种扫描方式呢

矩阵按键的原理是什么?
矩阵按键有哪几种扫描方式呢?
如何去实现STM32矩阵按键控制IO口的代码呢?



回帖(1)

李咏琪

2022-1-18 14:32:37
一 .矩阵按键原理
矩阵按键有两种扫描方式:
方法一:
逐行扫描:我们可以通过低四位轮流输出低电平来对矩阵键盘进行逐行扫描,当高四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
方法二:
行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
此次采用的是行扫描方式,与单片机连接如下:

C4 -->PB7 C3–>PB6 C2–>PB5 C1–>PB4
R1–>PB3 R2–>PB2 R3–>PB1 R4–>PB0

**二.完整程序**
最开始我使用的是GPIOD的Pin0-Pin5,但是导致了LCD无法正常使用,猜测是GPIOD中的某个IO在LCD中也使用了,导致冲突,具体是哪一个还不知道(技术太菜,LCD里面太多内容,看不懂.....)
1.MatrixButton.h头文件:


#ifndef __MatrixButton_H
#define __MatrixButton_H
#include "sys.h"
#define DelayTimes 10
void GPIOF_Int_Init(void);
void GPIOB_Int_Init(void);
void KEY_Scan(void);
void Multiple_Control(void);
#endif


2.MatrixButton.c文件代码:

#include "MatrixButton.h"
#include "delay.h"
u16 KeyValue=17;//17只是为了在没有按键按下的时候给一个数值让LCD显示
void GPIOF_Int_Init(void) //(这个函数不属于矩阵按键配置,初始化所要控制的IO口)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF时钟
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//IO输出引脚选用PF0-PF5
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//输出模式
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速度50MHZ
        GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉
        GPIO_Init(GPIOF,&GPIO_InitStructure);//初始化GPIOF
}
void GPIOB_Int_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能GPIOB的时钟
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;//输出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
       
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;//输入模式,用来检测哪一行按下
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
               
}
void KEY_Scan(void)                                //(行列扫描方式的矩阵按键配置)                                       
{
        GPIO_ResetBits(GPIOB,GPIO_Pin_3);         //第一行检测
        GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);                              
        if(((GPIOB->IDR )&0xF0)!=0xF0)         //说明PD4-PD7状态发生变化,列检测
        {
                delay_ms(DelayTimes);                        //按键消抖
                if(((GPIOB->IDR )&0xF0)!=0xF0)                 //再次判断是否有按键按下
                {
                        switch((GPIOB->IDR )&0xF7)//检测输入数据寄存器PB4-PB7对应位的电平状态
                        {
                                case 0xE7:KeyValue=1;break;//说明PB4接收到低电平,第一行第一列对应第一个按键
                                case 0xD7:KeyValue=2;break;
                                case 0xB7:KeyValue=3;break;
                                case 0x77:KeyValue=4;break;
                                default:break;
                        }


                 }       
         }
        GPIO_ResetBits(GPIOB,GPIO_Pin_2);
        GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3);
        if(((GPIOB->IDR )&0xF0)!=0xF0)         //说明PD4-PD7状态发生变化,列检测
        {
                delay_ms(DelayTimes);                                                                        //按键消抖
                if(((GPIOB->IDR )&0xF0)!=0xF0)                 //再次判断是否有按键按下
                {
                        switch((GPIOB->IDR )&0xFB)
                        {
                                case 0xEB:KeyValue=5;break;
                                case 0xDB:KeyValue=6;break;
                                case 0xBB:KeyValue=7;break;
                                case 0x7B:KeyValue=8;break;
                                default:break;
                        }


                }               
         }
         GPIO_ResetBits(GPIOB,GPIO_Pin_1);                //Pin1输出低电平
         GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3);//Pin0,Pin2,Pin3输出高电平
         if(((GPIOB->IDR )&0xF0)!=0xF0)         //说明PD4-PD7状态发生变化,列检测
        {
                delay_ms(DelayTimes);                                                                        //按键消抖
                if(((GPIOB->IDR )&0xF0)!=0xF0)                //再次判断是否有按键按下
                {
                        switch((GPIOB->IDR )&0xFD)
                                 {
                                        case 0xED:KeyValue=9;break;
                                        case 0xDD:KeyValue=10;break;
                                        case 0xBD:KeyValue=11;break;
                                        case 0x7D:KeyValue=12;break;
                                        default: break;
                                }


                 }       
         }       


        GPIO_ResetBits(GPIOB,GPIO_Pin_0);                         //Pin0输出低电平
        GPIO_SetBits(GPIOB,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);//Pin1-Pin3输出高电平
        if(((GPIOB->IDR )&0xF0)!=0xF0)         //说明PD4-PD7状态发生变化,列检测
        {
                delay_ms(DelayTimes);                                                                        //按键消抖
                if(((GPIOB->IDR )&0xF0)!=0xF0)                 //再次判断是否有按键按下
                {
                        switch((GPIOB->IDR )&0xFE)
                                {
                                        case 0xEE:KeyValue=13;break;
                                    case 0xDE:KeyValue=14;break;
                                    case 0xBE:KeyValue=15;break;
                                    case 0x7E:KeyValue=16;break;
                                        default:break;
                                }
                 }
         }
       
       
                                                         
}
void Multiple_Control(void)//控制IO口输出(这个函数通过矩阵键盘的按键控制IO口输出)
{
        if(KeyValue!=17)         //说明有按键按下
        {
                switch(KeyValue)
                {
                        case 1:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//000
                        }
                        case 2:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2);
                                GPIO_SetBits(GPIOF,GPIO_Pin_0);break;//001
                        }
                        case 3:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2);
                                GPIO_SetBits(GPIOF,GPIO_Pin_1);break;//010
                        }
                        case 4:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_2);
                                GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);break;//011
                        }
                        case 5:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);
                                GPIO_SetBits(GPIOF,GPIO_Pin_2);break;//100
                        }
                        case 6:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_1);
                                GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2);break;//101
                                                               
                        }
                        case 7:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_0);
                                GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2);break;//110
                                                               
                        }
                        case 8:
                        {
                                GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//111
                        }
                        case 9:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//000
                        }
                        case 10:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5);
                                GPIO_SetBits(GPIOF,GPIO_Pin_3);break;//001
                        }
                        case 11:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_5);
                                GPIO_SetBits(GPIOF,GPIO_Pin_4); break;//010
                        }
                        case 12:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_5);
                                GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4);break;//011
                        }
                        case 13:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4);
                                GPIO_SetBits(GPIOF,GPIO_Pin_5);break;//100
                        }
                        case 14:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_4);
                                GPIO_SetBits(GPIOF,GPIO_Pin_5|GPIO_Pin_3);break;//101
                        }
                        case 15:
                        {
                                GPIO_ResetBits(GPIOF,GPIO_Pin_3);
                                GPIO_SetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5);break;//110
                        }
                        case 16:
                        {
                                GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//111
                        }
                }
               
        }
       
}
       
3.主函数main.c:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "MatrixButton.h"
#include "lcd.h"
extern u16 KeyValue;
int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //设置系统中断优先级分组2
        delay_init(168);                                                                       //初始化延时函数
        uart_init(115200);                                                                        //初始化串口波特率为115200
        LED_Init();                                                                                        //初始化LED
        GPIOF_Int_Init();
        LED0=0;
        LCD_Init();                                                                         //初始化LCD接口
        GPIOB_Int_Init();                                                                        //初始化矩阵键盘所连接IO口
        LCD_Display_Dir(1);                                                                    //横屏显示       
        POINT_COLOR=RED;
       
        while(1)
        {
                if(KeyValue!=KeyValue)//按键值改变时才清屏
                        LCD_Clear(WHITE);
                LCD_ShowString(30,150,200,16,16,"KeyValue_is:"); //这里显示了KeyValue_is:
                KEY_Scan();                //行扫描矩阵按键
                LCD_ShowxNum(134,150,KeyValue,2,16,0);
                Multiple_Control();                        //矩阵按键控制IO口输出
                LED0=!LED0;
                delay_ms(50);
               
        }
}






举报

更多回帖

发帖
×
20
完善资料,
赚取积分