矩形键盘

介绍

什么是矩阵键盘

矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组,由于电路设计时需要更多的外部输入,单独的控制一个按键需要浪费很多的IO资源,所以就有了矩阵键盘,常用的矩阵键盘有4X4和8X8,其中用的最多的是4X4。
4

矩阵键盘的原理

矩阵键盘又称为行列式键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
在行线和列线的每一个交叉点上,设置一个按键。这样键盘中按键的个数是4×4个。
这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。由于单片机IO端口具有线与的功能,因此当任意一个按键按下时,行和列都有一根线被线与,通过运算就可以得出按键的坐标从而判断按键键值。
原理如同矩阵数列的行列式。

驱动电路图

按4*4矩阵搭建的按键矩阵还是比较简单的,也有的人为了保证电路的稳定性,加上二极管保护和上拉电阻,但是一般要求不太高的电路就不需要加了,向下面设置的电路那样就可以了。

软件程序实现

在这里宏定义一些GPIO的信息。

KEY.h

#ifndef _KEY_H
#define _KEY_H
#include "stm32f10x.h"
//引脚
#define S0 GPIO_Pin_0
#define S1 GPIO_Pin_1
#define S2 GPIO_Pin_2
#define S3 GPIO_Pin_3
#define S4 GPIO_Pin_4
#define S5 GPIO_Pin_5
#define S6 GPIO_Pin_6
#define S7 GPIO_Pin_7
//GPIO寄存器
#define KEY_PORT GPIOB
//时钟
#define RCC_APB2_KEY  RCC_APB2Periph_GPIOB
//函数定义
void InitKey(void);
int NumKey(void);
//延时
void Delay( uint32_t count )
{
 for(; count!=0; count--);
}
#endif /* _KEY_H  */

在这里存放两个函数,一个是初始化矩形键盘GPIO口的函数,在函数里把前四个定义为推挽输出,后四个GPIO口定义为下拉输入。
另一个函数是键盘扫描函数,通过函数返回值确定是举行键盘的哪一个按键被按下。

KEY.c

#include "KEY.h"
void InitKey(void)//初始化KEY的GPIO
{
 //打开GPIO时钟
 RCC_APB2PeriphClockCmd(RCC_APB2_KEY,ENABLE);
 //把S0,S1,S2,S3配置为推挽输出
 GPIO_InitTypeDef   GPIOInit;
 GPIOInit.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
 GPIOInit.GPIO_Speed=GPIO_Speed_50MHz;
 GPIOInit.GPIO_Pin=S0|S1|S2|S3;
 GPIO_Init(KEY_PORT,&GPIOInit); 
 
 //把S4,S5,S6,S7配置为下拉输入
 GPIOInit.GPIO_Mode=GPIO_Mode_IPU;
 GPIOInit.GPIO_Pin=S4|S5|S6|S7;
 GPIO_Init(KEY_PORT,&GPIOInit); 
 
  //0--3输出高,4--7输出低
  GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
  GPIO_ResetBits(GPIOC,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); 
  
}
int NumKey(void)  //扫描键值
{
 int KeyVal=0;     //键值,后面自己设定的,用来设置按键的序号
 u16 KeyWrite=0;   //写给GPIO的值 
 GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0 | 0xf));//0--3全部输出高 
 if((KEY_PORT->IDR&0x00f0)==0x0000)   //如果4--7全为0,表示没有按键按下,返回值设置为-1
  return -1;
  
 else
 {
  Delay(0xF);//消抖
   if((KEY_PORT->IDR&0x00f0)==0x0000)   //如果4-7全为0,表示刚才是抖动造成的
  return -1; 
 }
 GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x1));//让0-3输出0001
 
 switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
 {
  case 0x0010: KeyVal=16;break;
  case 0x0020: KeyVal=12;break;
  case 0x0040: KeyVal=8; break;
  case 0x0080: KeyVal=4; break; 
 }
 
 GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x2));//让0-3输出0010
 switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
 {
  case 0x0010: KeyVal=15;break;
  case 0x0020: KeyVal=11;break;
  case 0x0040: KeyVal=7; break;
  case 0x0080: KeyVal=3; break; 
 }
 GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x4));//让0-3输出0100
 switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
 {
  case 0x0010: KeyVal=14;break;
  case 0x0020: KeyVal=10;break;
  case 0x0040: KeyVal=6; break;
  case 0x0080: KeyVal=2; break; 
 }
 GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x8));//让0-3输出1000
 switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
 {
  case 0x0010: KeyVal=13;break;
  case 0x0020: KeyVal=9;break;
  case 0x0040: KeyVal=5; break;
  case 0x0080: KeyVal=1; break;
 }
 return KeyVal;
}

想了解更多嵌入式知识,欢迎关注我的项目实战专栏。
还可关注公众号,了解更多。

猜你喜欢

转载自blog.csdn.net/qq_44629109/article/details/107577653