4x4阵列键盘原理
端口反转方案检测方法:1.先将PA0-PA3设置为上拉电阻输入模式,并设为高电平,再将PA4-PA7设置为推挽输出模式,并设置为低电平,相当于接地,所以当按下某一个按键时,PA0-PA3就能检测1、2、3、4哪一排被按下。
2.将PA0-PA3与PA4-PA7设置反转,就能检测哪一列被按下。结合1.就可以知道哪个键被按下了。
此外还有逐行扫描方案等。
阵列键盘驱动程序
void KEYPAD4x4_Init(void){ //微动开关的接口初始化
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEYa | KEYb | KEYc | KEYd; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻
GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2 | KEY3 | KEY4; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 //上拉电阻
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
}
void KEYPAD4x4_Init2(void){ //微动开关的接口初始化2(用于IO工作方式反转)
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构
GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2 | KEY3 | KEY4; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻
GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEYa | KEYb | KEYc | KEYd; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 //上拉电阻
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
}
u8 KEYPAD4x4_Read (void){//键盘处理函数
u8 a=0,b=0;//定义变量
KEYPAD4x4_Init();//初始化IO
GPIO_ResetBits(KEYPAD4x4PORT,KEY1|KEY2|KEY3|KEY4);
GPIO_SetBits(KEYPAD4x4PORT,KEYa|KEYb|KEYc|KEYd);
if(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYa) || //查寻键盘口的值是否变化
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYb) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYc) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYd)){
delay_ms (20);//延时20毫秒
if(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYa) || //查寻键盘口的值是否变化
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYb) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYc) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYd)){
a = GPIO_ReadInputData(KEYPAD4x4PORT)&0xff;//键值放入寄存器a
}
KEYPAD4x4_Init2();//IO工作方式反转
GPIO_SetBits(KEYPAD4x4PORT,KEY1|KEY2|KEY3|KEY4);
GPIO_ResetBits(KEYPAD4x4PORT,KEYa|KEYb|KEYc|KEYd);
b = GPIO_ReadInputData(KEYPAD4x4PORT)&0xff;//将第二次取得值放入寄存器b
a = a|b;//将两个数据相或
switch(a){//对比数据值
case 0xee: b = 16; break;//对比得到的键值给b一个应用数据(0xee即为按下了0键)
case 0xed: b = 15; break;
case 0xeb: b = 14; break;
case 0xe7: b = 13; break;
case 0xde: b = 12; break;
case 0xdd: b = 11; break;
case 0xdb: b = 10; break;
case 0xd7: b = 9; break;
case 0xbe: b = 8; break;
case 0xbd: b = 7; break;
case 0xbb: b = 6; break;
case 0xb7: b = 5; break;
case 0x7e: b = 4; break;
case 0x7d: b = 3; break;
case 0x7b: b = 2; break;
case 0x77: b = 1; break;
default: b = 0; break;//键值错误处理
}
while(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY1) || //等待按键放开
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY2) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY3) ||
!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY4));
delay_ms (20);//延时20毫秒
}
return (b);//将b作为返回值
}
按键应用
#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "KEYPAD4x4.h"
int main (void){//主程序
u8 s;
delay_ms(500); //上电时等待其他器件就绪
RCC_Configuration(); //系统时钟初始化
RELAY_Init();//继电器初始化
I2C_Configuration();//I2C初始化
OLED0561_Init(); //OLED初始化
OLED_DISPLAY_8x16_BUFFER(0," YoungTalk "); //显示字符串
OLED_DISPLAY_8x16_BUFFER(3," KEYPAD4x4 TEST "); //显示字符串
KEYPAD4x4_Init();//阵列键盘初始化
while(1){
s=KEYPAD4x4_Read();//读出按键值
if(s!=0){ //如按键值不是0,也就是说有按键操作,则判断为真
//-------------------------"----------------"
OLED_DISPLAY_8x16_BUFFER(6," KEY NO. "); //显示字符串
OLED_DISPLAY_8x16(6,8*8,s/10+0x30);//
OLED_DISPLAY_8x16(6,9*8,s%10+0x30);//
}
}
}