STM32 4*4矩阵键盘实现原理(附程序)
:在了解矩阵键盘之前,有必要了解一下独立按键的触发原理。下图为常用独立按键接线图。
:按键一端接地,另一端接单片机的GPIO。当按键没有按下时,这个路径实际上是开路,我们通常将单片机的引脚设置为输入上拉状态。所以当按钮未按下时,该引脚读取的电平始终为高电平。当按下按钮时,此时的引脚会被地面强行拉下。此时该引脚读取的电平为低电平,表示按键已被按下。独立按钮到这里就完成了,很简单。矩阵按键由多个独立按键组成,其触发原理与独立按键相同,但电路和程序扫描不同,稍微复杂一些。
通常用的最多的矩阵键盘是4*4的。如下图:
在编程中,扫描通常是逐行逐列进行,4*4矩阵键盘一共需要单片机的8个GPIO引脚,控制行的引脚设置为输出,并且控制列的管脚设置为输入上拉。
先扫描第一行,然后PD0~PD2输出高电平,PD3输出低电平4*4矩阵键盘判断程序,标记为0xF7。行确定后4*4矩阵键盘判断程序,开始扫描列,控制列的管脚为Input管脚,与0XF7相与,如果哪一位为0,则证明按下了哪一位。未按下按键时,IO口状态为**1111 0000,**扫描第一行输出PD3低电平,其他行输出高电平,即1111 0111,假设第一行按键按下,此时PD4管脚读低电平,此时读管脚发生变化
程序如下:
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
程序结果如下:
© 版权声明
THE END
喜欢就支持一下吧
请登录后发表评论
注册
社交帐号登录