当前位置:   article > 正文

stm32矩阵键盘学习笔记_stm32矩阵按键端口配置

stm32矩阵按键端口配置

矩阵键盘简介

  1. 什么是矩阵键盘
    矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组,由于电路设计时需要更多的外部输入,单独的控制一个按键需要浪费很多的IO资源,所以就有了矩阵键盘,常用的矩阵键盘有4X4和8X8,其中用的最多的是4X4。
  2. 矩阵键盘的原理
    矩阵键盘又称为行列式键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
    在行线和列线的每一个交叉点上,设置一个按键。这样键盘中按键的个数是4×4个。
    这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。由于单片机IO端口具有线与的功能,因此当任意一个按键按下时,行和列都有一根线被线与,通过运算就可以得出按键的坐标从而判断按键键值。

矩阵键盘扫描原理

在这里插入图片描述

  1. 行扫描的原理:因为如果有按键按下的话,某一个输入的引脚就会跟对应的输出引脚连接,因为输出为高电平,所以对应的输入引脚会被拉高,读取引脚的状态,判断哪个引脚被拉高就可以知道哪一行有按键按下了;总的来说是通过高四位输出高电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一行按键被按下。
  2. 再通过列操作模块:
#define KEY_CLO0_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define KEY_CLO1_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET)
#define KEY_CLO2_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET)
#define KEY_CLO3_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)

#define KEY_CLO0_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET) 
#define KEY_CLO1_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET)
#define KEY_CLO2_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET)
#define KEY_CLO3_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

来进行列扫描。

端口的配置

介绍完矩阵键盘的扫描原理了我们该通过keli来实现我们想要的功能啦,首先我们要进行的就是对我们所需要的端口进行配置,如下:


//端口的配置
void key_init(){

	GPIO_InitTypeDef GPIO_InitStruture;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打开PE时钟
	
	//定义PB12、PB13、PB14、PB15为推挽输出 
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
	GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruture);
	
	//定义PD8、PD9、PD10、PD11为上拉输入 分别定义为四行
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
	GPIO_Init(GPIOD,&GPIO_InitStruture);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

相关函数的编写

配置完我们所需要的端口,接下来我们就应该编写相关函数啦。

  1. 行扫描函数:
//如果为1,代表没有按键被按下,如果为0,代表有按键被按下
char KEY_ROW_SCAN(void)
{
    //读出行扫描状态
    Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));
    
	if(Key_row[0] != 0x0f)         //不是1111,代表肯定有一个0行
    {
      delay_ms(10);                    //消抖
      if(Key_row[0] != 0x0f)
		  //0111 1011 1101 1110
        {   
                //printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);
                switch(Key_row[0])
                {
                    case 0x07:         //0111 判断为该列第1行的按键按下
                        return 1;
                    case 0x0b:         //1011 判断为该列第2行的按键按下
                        return 2;
                    case 0x0d:         //1101 判断为该列第3行的按键按下
                        return 3;
                    case 0x0e:         //1110 判断为该列第4行的按键按下
                        return 4;
                    default :
                        return 0;
                }
        }
        else return 0;
    }
    else return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  1. 按键扫描函数:
char KEY_SCAN(void)
{    
    char Key_Num=0;            //1-16对应的按键数
    char key_row_num=0;        //行扫描结果记录
    
    KEY_CLO0_OUT_LOW;        
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);  //消抖
        Key_Num = 0 + key_row_num;
    }
    KEY_CLO0_OUT_HIGH;
    
    KEY_CLO1_OUT_LOW;        
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);
        Key_Num = 4 + key_row_num;
    }
    KEY_CLO1_OUT_HIGH;
    
    KEY_CLO2_OUT_LOW;    
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);
    Key_Num = 8 + key_row_num;
    }
    KEY_CLO2_OUT_HIGH;
    
    KEY_CLO3_OUT_LOW;    
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    {
        while(KEY_ROW_SCAN() != 0);
        Key_Num = 12 + key_row_num;
    }
    KEY_CLO3_OUT_HIGH;
    
    return Key_Num;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

主函数与其他

  1. 主函数:
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key16.h"
#include "stdio.h"
#include "usart.h"


int main(void)
{
	vu8 key=0;
	char key_confirm;
	led_init();
	delay_init();
	key_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);
	
	while(1)
	{
		key_confirm = KEY_SCAN();
		if(key_confirm>0&&key_confirm<17){
			printf("Key_NUM = %d \r\n",key_confirm); //按下1-16个按键的操作
      printf("= = = = = = = = = = = \r\n");		
		}	
	}	

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  1. key.c:
#include "key16.h"
#include "delay.h"


uint8_t Key_row[1]={0xff};   //定义一个数组,存放行扫描状态

//端口的配置
void key_init(){

	GPIO_InitTypeDef GPIO_InitStruture;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打开PE时钟
	
	//定义PB12、PB13、PB14、PB15为推挽输出 
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
	GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruture);
	
	//定义PD8、PD9、PD10、PD11为上拉输入 分别定义为四行
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
	GPIO_Init(GPIOD,&GPIO_InitStruture);
	

}

/***
 *函数名:KEY_ROW_SCAN
 *功  能:按键行扫描
 *返回值:1~4,对应1~4行按键位置
 */
//如果为1,代表没有按键被按下,如果为0,代表有按键被按下
char KEY_ROW_SCAN(void)
{
    //读出行扫描状态
    Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);
    Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));
    
	if(Key_row[0] != 0x0f)         //不是1111,代表肯定有一个0行
    {
      delay_ms(10);                    //消抖
      if(Key_row[0] != 0x0f)
		  //0111 1011 1101 1110
        {   
                //printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);
                switch(Key_row[0])
                {
                    case 0x07:         //0111 判断为该列第1行的按键按下
                        return 1;
                    case 0x0b:         //1011 判断为该列第2行的按键按下
                        return 2;
                    case 0x0d:         //1101 判断为该列第3行的按键按下
                        return 3;
                    case 0x0e:         //1110 判断为该列第4行的按键按下
                        return 4;
                    default :
                        return 0;
                }
        }
        else return 0;
    }
    else return 0;
}

/***
 *函数名:KEY_SCAN
 *功  能:4*4按键扫描
 *返回值:0~16,对应16个按键
 */
char KEY_SCAN(void)
{    
    char Key_Num=0;            //1-16对应的按键数
    char key_row_num=0;        //行扫描结果记录
    
    KEY_CLO0_OUT_LOW;        
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);  //消抖
        Key_Num = 0 + key_row_num;
    }
    KEY_CLO0_OUT_HIGH;
    
    KEY_CLO1_OUT_LOW;        
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);
        Key_Num = 4 + key_row_num;
        //printf("Key_Clo_2\r\n");
    }
    KEY_CLO1_OUT_HIGH;
    
    KEY_CLO2_OUT_LOW;    
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    { 
        while(KEY_ROW_SCAN() != 0);
    Key_Num = 8 + key_row_num;
        //printf("Key_Clo_3\r\n");
    }
    KEY_CLO2_OUT_HIGH;
    
    KEY_CLO3_OUT_LOW;    
    if( (key_row_num=KEY_ROW_SCAN()) != 0 )
    {
        while(KEY_ROW_SCAN() != 0);
        Key_Num = 12 + key_row_num;
    }
    KEY_CLO3_OUT_HIGH;
    
    return Key_Num;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  1. key.h:
#ifndef _KEY16_H
#define _KEY16_H

#include "sys.h"
#include "stm32f10x.h"

#include <string.h>


void key_init();
char KEY_SCAN(void);
char KEY_ROW_SCAN(void);
void HW_KEY_FUNCTION(void);


#define KEY_CLO0_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define KEY_CLO1_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET)
#define KEY_CLO2_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET)
#define KEY_CLO3_OUT_LOW  GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)

#define KEY_CLO0_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET) 
#define KEY_CLO1_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET)
#define KEY_CLO2_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET)
#define KEY_CLO3_OUT_HIGH  GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)


#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

串口的接线与矩阵键盘的接线

  1. 首先我们先接串口,把串口的VCC和GND分别接到主板上的3.3V和GND上(注意要把串口上的插线帽调整到3.3V,不然容易把板子烧坏,板子烧坏了那可就成大xx了),然后再把串口上的TXD和RXD分别连到主板的RXD和TXD。
  2. 然后我们来接矩阵键盘,要用到八根线,R1 ~ R4分别连到主板上的PD8 ~ PD11,C1 ~ C4分别连到主板上的PB12 ~ PB15.
    在这里插入图片描述

load与运行调试

好啦,所有准备工作都完成啦!!又到了我们激动人心的时刻啦!!
运行成功图如下:
在这里插入图片描述
over。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/302183
推荐阅读
相关标签
  

闽ICP备14008679号