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
暂无评论