STM32 4*4矩阵键盘实现原理(附程序)

STM32 4*4矩阵键盘实现原理(附程序)

: 理解矩阵键盘之前,先要了解一下独立按键的触发原理。下图是普通独立 按键的接线图。
在这里插入图片描述

: 按键的一端接地,一端接MCU的GPIO。当按键没有被按下的时候,这条路其实是一个断路,我们通常会将单片机该引脚设置成输入上拉状态。所以当按键没有按下的时候,这个引脚读到的电平一直是高电平。当按下按键的时候,那么此时的引脚会被地强行拉低,此时这个引脚读到的电平为低电平,那说明按键已经被按下。独立按键到这里已经说完了,很简单。矩阵按键是由多个独立按键组成的,所以它的触发原理和独立按键相同,只是在电路和程序扫描上不同,略微复杂一点。

  通常用的最多的矩阵键盘是4*4的。如下图:

在这里插入图片描述
程序设计上通常采用逐行逐列进行扫描,4*4的矩阵键盘一共需要8个单片机的GPIO引脚,将控制行的引脚设置成输出,控制列的引脚设置成输入上拉。

先扫描第一行,那么就将PD0~PD2输出高电平,将PD3输出低电平,记为0xF7,行确定好后,开始扫描列,控制列的引脚为输入引脚,将其和0XF7相与,如果哪一位为0,那么就证明哪一个被按下。按键没有被按下的时候,IO口的状态为 **1111 0000 ,**扫描第一行将PD3输出低电平,其他行输出高电平,即为1111 0111,假设第一个按键被按下,那么此时PD4引脚读到低电平,那么读到的引脚变化

GPIOD->IDR & 1111 0111=1110 0111//这样就证明了第一个按键被按下。以此类推。

程序如下:

key_board.c

#include "stm32f10x.h"
#include "delay.h"
#include "key_board.h"


//uint8_t Send_F=0;


void Keyboard_GPIO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    KEYBOARD_GPIO_CLK_FUN(KEYBOARD_GPIO_CLK,ENABLE);
    
    //LINE    
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN0|KEYBOARD_GPIO_PIN1|KEYBOARD_GPIO_PIN2|KEYBOARD_GPIO_PIN3;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);

    //ROW
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN4|KEYBOARD_GPIO_PIN5|KEYBOARD_GPIO_PIN6|KEYBOARD_GPIO_PIN7;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);
}

uint16_t keyboard_scan(void)
{
    uint16_t key_val=0;
    uint16_t temp=0;
	
	
	/*************Scan  1st Line************************/

    GPIOD->ODR=0X00;

    GPIOD->ODR=0XF7;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XF7);
            switch(temp)
            {
                case 0xE7:  key_val=1;   break;

                case 0xD7:  key_val=2;   break;

                case 0xB7:  key_val=3;   break;

                case 0x77:  key_val=4;   break;

                default:    key_val=0;   break;
            }
        }
    }
    
		/*************Scan  2st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFB;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFB);
            switch(temp)
            {
                case 0xEB:  key_val=5;  break;

                case 0xDB:  key_val=6;  break;

                case 0xBB:  key_val=7;  break;

                case 0x7B:  key_val=8;  break;

                default:    key_val=0;  break;
            }
        }
    }

		/*************Scan  3st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFD;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFD);
            switch(temp)
            {
                case 0xED:  key_val=9;   break;

                case 0xDD:  key_val=10;  break;

                case 0xBD:  key_val=11;  break;

                case 0x7D:  key_val=12;  break;

                default:    key_val=0;   break;
            }
        }
    }

		/*************Scan  4st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFE;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFE);
            switch(temp)
            {
                case 0xEE:  key_val=13;  break;

                case 0xDE:  key_val=14;  break;

                case 0xBE:  key_val=15;  break;

                case 0x7E:  key_val=16;  break;

                default:    key_val=0;   break;
            }
        }
    }

    return key_val;

}

key_board.h

#include "stm32f10x.h"

#ifndef     _KEY_BOARD_H_
#define     _KEY_BOARD_H_



#define   KEYBOARD_GPIO_PORT          GPIOD
#define   KEYBOARD_GPIO_CLK_FUN       RCC_APB2PeriphClockCmd
#define   KEYBOARD_GPIO_CLK           RCC_APB2Periph_GPIOD


//line    行
#define   KEYBOARD_GPIO_PIN0           GPIO_Pin_0
#define   KEYBOARD_GPIO_PIN1           GPIO_Pin_1
#define   KEYBOARD_GPIO_PIN2           GPIO_Pin_2
#define   KEYBOARD_GPIO_PIN3           GPIO_Pin_3



//row      列
#define   KEYBOARD_GPIO_PIN4           GPIO_Pin_4
#define   KEYBOARD_GPIO_PIN5           GPIO_Pin_5
#define   KEYBOARD_GPIO_PIN6           GPIO_Pin_6
#define   KEYBOARD_GPIO_PIN7           GPIO_Pin_7



//extern uint8_t Send_F;

extern void Keyboard_GPIO_Config(void);
extern uint16_t keyboard_scan(void);

#endif

程序运行结果如下:

在这里插入图片描述

版权声明:本文为CSDN博主「AX_liujiucheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr_liu_JC/article/details/119426115

STM32 4*4矩阵键盘实现原理(附程序)

: 理解矩阵键盘之前,先要了解一下独立按键的触发原理。下图是普通独立 按键的接线图。
在这里插入图片描述

: 按键的一端接地,一端接MCU的GPIO。当按键没有被按下的时候,这条路其实是一个断路,我们通常会将单片机该引脚设置成输入上拉状态。所以当按键没有按下的时候,这个引脚读到的电平一直是高电平。当按下按键的时候,那么此时的引脚会被地强行拉低,此时这个引脚读到的电平为低电平,那说明按键已经被按下。独立按键到这里已经说完了,很简单。矩阵按键是由多个独立按键组成的,所以它的触发原理和独立按键相同,只是在电路和程序扫描上不同,略微复杂一点。

  通常用的最多的矩阵键盘是4*4的。如下图:

在这里插入图片描述
程序设计上通常采用逐行逐列进行扫描,4*4的矩阵键盘一共需要8个单片机的GPIO引脚,将控制行的引脚设置成输出,控制列的引脚设置成输入上拉。

先扫描第一行,那么就将PD0~PD2输出高电平,将PD3输出低电平,记为0xF7,行确定好后,开始扫描列,控制列的引脚为输入引脚,将其和0XF7相与,如果哪一位为0,那么就证明哪一个被按下。按键没有被按下的时候,IO口的状态为 **1111 0000 ,**扫描第一行将PD3输出低电平,其他行输出高电平,即为1111 0111,假设第一个按键被按下,那么此时PD4引脚读到低电平,那么读到的引脚变化

GPIOD->IDR & 1111 0111=1110 0111//这样就证明了第一个按键被按下。以此类推。

程序如下:

key_board.c

#include "stm32f10x.h"
#include "delay.h"
#include "key_board.h"


//uint8_t Send_F=0;


void Keyboard_GPIO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    KEYBOARD_GPIO_CLK_FUN(KEYBOARD_GPIO_CLK,ENABLE);
    
    //LINE    
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN0|KEYBOARD_GPIO_PIN1|KEYBOARD_GPIO_PIN2|KEYBOARD_GPIO_PIN3;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);

    //ROW
    GPIO_InitStruct.GPIO_Pin=KEYBOARD_GPIO_PIN4|KEYBOARD_GPIO_PIN5|KEYBOARD_GPIO_PIN6|KEYBOARD_GPIO_PIN7;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(KEYBOARD_GPIO_PORT,&GPIO_InitStruct);
}

uint16_t keyboard_scan(void)
{
    uint16_t key_val=0;
    uint16_t temp=0;
	
	
	/*************Scan  1st Line************************/

    GPIOD->ODR=0X00;

    GPIOD->ODR=0XF7;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XF7);
            switch(temp)
            {
                case 0xE7:  key_val=1;   break;

                case 0xD7:  key_val=2;   break;

                case 0xB7:  key_val=3;   break;

                case 0x77:  key_val=4;   break;

                default:    key_val=0;   break;
            }
        }
    }
    
		/*************Scan  2st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFB;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFB);
            switch(temp)
            {
                case 0xEB:  key_val=5;  break;

                case 0xDB:  key_val=6;  break;

                case 0xBB:  key_val=7;  break;

                case 0x7B:  key_val=8;  break;

                default:    key_val=0;  break;
            }
        }
    }

		/*************Scan  3st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFD;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFD);
            switch(temp)
            {
                case 0xED:  key_val=9;   break;

                case 0xDD:  key_val=10;  break;

                case 0xBD:  key_val=11;  break;

                case 0x7D:  key_val=12;  break;

                default:    key_val=0;   break;
            }
        }
    }

		/*************Scan  4st Line************************/
    GPIOD->ODR=0X00;

    GPIOD->ODR=0XFE;

    if((GPIOD->IDR&0XF0)!=0XF0)
    {
        delay_ms(50);

        if((GPIOD->IDR & 0XF0)!=0XF0)
        {
            temp=(GPIOD->IDR&0XFE);
            switch(temp)
            {
                case 0xEE:  key_val=13;  break;

                case 0xDE:  key_val=14;  break;

                case 0xBE:  key_val=15;  break;

                case 0x7E:  key_val=16;  break;

                default:    key_val=0;   break;
            }
        }
    }

    return key_val;

}

key_board.h

#include "stm32f10x.h"

#ifndef     _KEY_BOARD_H_
#define     _KEY_BOARD_H_



#define   KEYBOARD_GPIO_PORT          GPIOD
#define   KEYBOARD_GPIO_CLK_FUN       RCC_APB2PeriphClockCmd
#define   KEYBOARD_GPIO_CLK           RCC_APB2Periph_GPIOD


//line    行
#define   KEYBOARD_GPIO_PIN0           GPIO_Pin_0
#define   KEYBOARD_GPIO_PIN1           GPIO_Pin_1
#define   KEYBOARD_GPIO_PIN2           GPIO_Pin_2
#define   KEYBOARD_GPIO_PIN3           GPIO_Pin_3



//row      列
#define   KEYBOARD_GPIO_PIN4           GPIO_Pin_4
#define   KEYBOARD_GPIO_PIN5           GPIO_Pin_5
#define   KEYBOARD_GPIO_PIN6           GPIO_Pin_6
#define   KEYBOARD_GPIO_PIN7           GPIO_Pin_7



//extern uint8_t Send_F;

extern void Keyboard_GPIO_Config(void);
extern uint16_t keyboard_scan(void);

#endif

程序运行结果如下:

在这里插入图片描述

版权声明:本文为CSDN博主「AX_liujiucheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr_liu_JC/article/details/119426115

生成海报
点赞 0

AX_liujiucheng

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32 4*4矩阵键盘实现原理(附程序)

STM32 4*4矩阵键盘实现原理(附程序) : 理解矩阵键盘之前,先要了解一下独立按键的触发原理。下图是普通独立 按键的接线图。 : 按键的一端接地,一端接MCU的GPIO。当按键

PCA9555详细学习

2022.01.27 控制寄存器和命令寄存器,及英文理解 一般8位作为地址,其中前四位时固定的,中间三位为地址配置,最后一位是读写位,即读是1,写是0 当地址