文章目录
- 一、元器件矩阵键盘说明
- 二、基于stm32f10c8t6 基础实验矩阵按键
- (1)实验功能实现说明
- (2)矩阵键盘原理
- (3)代码部分
- (4)效果展示
- 三、总结与扩展
- 附上参考文献链接与视频链接出处
一、元器件矩阵键盘说明
本次实验采用4*4矩阵键盘进行应用,矩阵键盘为了节约引脚的占用,提供了多行多列的排列组合为矩形的按键,所以为矩阵按键或矩阵键盘。如图所示:
矩阵键盘
二、基于stm32f10c8t6 基础实验矩阵按键
(1)实验功能实现说明
本实验通过stm32和矩阵按键实现点亮LED,以二进制的方式显示。如二进制的0000,对应四颗LED都熄灭;二进制的0001,对应第四颗LED点亮,其余三颗熄灭,以此类推;即1亮0灭。0.96寸OLED显示反馈的键值(以两个单位),如key1—01,key5----05,key11—11…;以按键响应对应的键值和二进制显示的LED。矩阵按键实现方法:1.响应对应中断的方法。2.行列扫描的方法。本实验主要是采用第二种方法,更容易理解。
(2)矩阵键盘原理
原理图
行列扫描法:
矩阵按键扫描方式理解图如下:
解释说明:左边的填充以横向理解,右边的填充以竖向理解。
首先可以看到0x00ff,表示行列的按键均未接触,0x00fe 竖向1110表示第一行接触,那么等待第一行的第几列进行下一步接触,当第一行的第一列同时响应接触,那么表示第一行第一列对应的LED以二进制0001的方式进行显示,即点亮第四颗灯。
0x00fd 竖向1101表示第二行接触,那么等待第二行的第几列进行下一步接触,当第二行的第三列同时响应接触,那么表示第二行第三列对应的LED以二进制1101的方式进行显示,即点亮第一、二、四颗灯。
0x00fb 竖向1011表示第三行接触,那么等待第三行的第几列进行下一步接触,当第三行的第一、三列同时响应接触,那么表示第三行第一、三列对应的LED以二进制0101的方式进行显示,即点亮第二、四颗灯。
第四行同理可得。
(3)代码部分
keys.c
#include "stm32f10x.h"
#include "keys.h"
#include "delay.h"
// //********************************************************************************
u8 FLAG = 0;void KEY_4x4_Init(void) //IO初始化
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Pin = KEY_HANG; //行 0123GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(KEY_PROT, &GPIO_InitStructure);GPIO_SetBits(KEY_PROT,KEY_HANG);//init GPIOA 上拉输入GPIO_InitStructure.GPIO_Pin = KEY1|KEY2|KEY3|KEY4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(KEY_PROT, &GPIO_InitStructure);GPIO_SetBits(KEY_PROT,KEY1|KEY2|KEY3|KEY4);}void KEY_Scan(u8 *key)
{ GPIO_Write(KEY_PROT,0x00fe);//第一行if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET)) {delay_ms(10);//去抖动 if(KEY1_Input==RESET){FLAG = 1;*key = 1;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));}else if(KEY2_Input==RESET){FLAG = 1;*key = 2;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));}else if(KEY3_Input==RESET){FLAG = 1;*key = 3;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));}else if(KEY4_Input==RESET){FLAG = 1;*key = 4;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));}else {FLAG = 0;GPIO_Write(KEY_PROT,0x00ff);}}GPIO_Write(KEY_PROT,0x00fd);//第二行if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET)){delay_ms(10);//去抖动 if(KEY1_Input==RESET){FLAG = 1;*key = 5;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));}else if(KEY2_Input==RESET){FLAG = 1;*key = 6;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));}else if(KEY3_Input==RESET){FLAG = 1;*key = 7;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));}else if(KEY4_Input==RESET){FLAG = 1;*key = 8;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));}else {FLAG = 0;GPIO_Write(KEY_PROT,0x00ff);}}GPIO_Write(KEY_PROT,0x00fb);//第三行if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET)){delay_ms(10);//去抖动 if(KEY1_Input==RESET){FLAG = 1;*key = 9;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));}else if(KEY2_Input==RESET){FLAG = 1;*key = 10;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));}else if(KEY3_Input==RESET){FLAG = 1;*key = 11;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));}else if(KEY4_Input==RESET){FLAG = 1;*key = 12;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));}else {FLAG = 0;GPIO_Write(KEY_PROT,0x00ff);}}GPIO_Write(KEY_PROT,0x00f7);//第四行if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET)){delay_ms(10);//去抖动 if(KEY1_Input==RESET){FLAG = 1;*key = 13;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));}else if(KEY2_Input==RESET){FLAG = 1;*key = 14;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));}else if(KEY3_Input==RESET){FLAG = 1;*key = 15;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));}else if(KEY4_Input==RESET){FLAG = 1;*key = 16;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));}else {FLAG = 0;GPIO_Write(KEY_PROT,0x00ff);}}}
keys.h
#ifndef __KEYS_H
#define __KEYS_H
// //********************************************************************************
//V1.1修改说明
//修改按键扫描函数,使整个代码可以支持SWD下载。
//
#include "stm32f10x.h"#define KEY_HANG 0x000f //0123
#define KEY1 GPIO_Pin_4
#define KEY2 GPIO_Pin_5
#define KEY3 GPIO_Pin_6
#define KEY4 GPIO_Pin_7 #define KEY1_Input GPIO_ReadInputDataBit(KEY_PROT,KEY1)
#define KEY2_Input GPIO_ReadInputDataBit(KEY_PROT,KEY2)
#define KEY3_Input GPIO_ReadInputDataBit(KEY_PROT,KEY3)
#define KEY4_Input GPIO_ReadInputDataBit(KEY_PROT,KEY4)#define KEY_PROT GPIOAextern u8 FLAG;void KEY_4x4_Init(void);//IO初始化
//u8 KEY_Scan(void);
void KEY_Scan(u8 *key); //按键扫描函数 #endif
main.c
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "keys.h"
//#include "usart.h"
#include "OLED.h"/*接线说明
PA0~PA3-------R4~R1 //行
PA4~PA7-------C4~C1 //列
*/u8 key = 0;u8 i;int main(void){LED_Init(); delay_init();KEY_4x4_Init();//uart_init(115200);OLED_Init();/*OLED初始化界面*/OLED_ShowChar(1, 1, 'A');OLED_ShowString(1, 3, "HelloWorld!");OLED_ShowNum(2, 1, 12345, 5);OLED_ShowSignedNum(2, 7, -66, 2);OLED_ShowHexNum(3, 1, 0xAA55, 4);OLED_ShowBinNum(4, 1, 0xAA55, 16);while(1){ KEY_Scan(&key); //获取键值keyif(FLAG == 1) //按键按下{FLAG = 0;OLED_Clear();OLED_ShowNum(2, 1, key, 2); //显示键值key//Printf("KEY = %d\r\n",key);if(key==1) //0001{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);GPIO_ResetBits(GPIOB,GPIO_Pin_15); } if(key==2) //0010{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_14); } if(key==3) //0011{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15); } if(key==4) //0100{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_13); } if(key==5) //0101{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14);GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15); } if(key==6) //0110{GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14); } if(key==7) //0111{GPIO_SetBits(GPIOB,GPIO_Pin_12);GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); } if(key==8) //1000{GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_12); } if(key==9) //1001{GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15); } if(key==10) //1010{GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14); } if(key==11) //1011{GPIO_SetBits(GPIOB,GPIO_Pin_13);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15); } if(key==12) //1100{GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13); } if(key==13) //1101{GPIO_SetBits(GPIOB,GPIO_Pin_14);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15); } if(key==14) //1110{GPIO_SetBits(GPIOB,GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14); } if(key==15) //1111{GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); } if(key==16) //来回闪烁4次{for(i=0;i<4;i++){GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15); delay_ms(1000); GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15); delay_ms(1000); } } //LCD12864_Write_Number(0x8d,key);}}}
(4)效果展示
矩阵按键实验效果:
矩阵按键
三、总结与扩展
总结:
根据以上内容,学习矩阵按键,跟轻触按键类似还是容易理解的,给输入信号给stm32以驱动LED相应点亮或熄灭。矩阵按键主要是应用需求多数按键解决引脚少的情况。
总结调试代码或硬件中,针对可能出现的问题,说明一下:
(1)出现按键响应慢的情况:因为矩阵按键模块的触发所用的为行列扫描,比中断触发响应的速度较慢;代码部分按键扫描延迟过高,或者去抖动(10ms~20ms)。
(2)出现按键硬件无响应的情况:可能是由于键盘模块引脚与stm32引脚接线错误或接反;也可能是对应引脚冲突占用,需要调用AFIO端口复用转换为普通I/O,也许即可解决;还可能是硬件坏了的问题,或者铜暴露出来导致的短路。
扩展: 可通过矩阵键盘模块可以做简易计算器、密码锁、功能键等实验。那么就分享到这,大胆尝试实践探索吧,欢迎讨论。
今日就分享到此了,要有信心一步步积累理论和实践经验,一起学习加油!
附上参考文献链接与视频链接出处
链接: 参考文献
链接: 参考视频
链接: 矩阵按键视频分享
链接: 源码例程
提取码:3232