关于stm32驱动矩阵键盘的一些问题,以及矩阵键盘的替代方法
关于矩阵键盘
对于一般的按键来说,我一般倾向于中断方式来触发。一是节省单片机的资源,不必让它来回扫描。二是中断非常高效,处理起来也很方便。但是对于矩阵键盘,我绞尽脑汁也没有想出来办法完全通过中断来实现。下面介绍一下我踩过的坑
中断+状态检测(坑)
先上图

上图是用立创eda画的,因为用的是微动开关,所以显得比较杂乱。看下图

这时我采用的方法是,P14,P15,P16,P17输入上拉,同时设为外部中断通道,下降沿触发。P10,P11,P12,P13输入下拉。这时设想的是,如果我按下按钮S1,电平被拉低,那么触发P14口中断,在中断内检测一下P10,P11,P12,P13哪个口的电平升高了,在此处是P10口,即可确定是S1按键被按下。但理想很丰满,显示很骨感。由于IO口设置的是输入上拉与输入下拉,在stm32内部上下拉电阻都为40K欧。这样按下按键后,连接按键的两个IO口的电平均为1.6V左右。在stm32内用的是TTL电平,高于2V算高电平,低于0.8V是低电平。那你说1.6V算什么嘛。
如果想要用这种方法,估计得设计电平转换电路了,但是一个矩阵键盘不值得,换个方法。
我于是想着换成外部上拉或下拉,IO口全部设成浮空输入。但是推理一下发现,这和上面哪个方法是差不多的,无非是外部上下拉。但是我可以改变外部上下拉电阻的大小,从而控制按下按钮后的状态电平,但这时问题又出现了,我只能满足一个方向,即如果我想满足在行的中断的条件,那么我将无法在列处检测到电平变化,我如果能在列处检测到电平变化,那么我的行将无法产生中断。
于是我想着将行设为推挽输出,不断的循环,但是只有一行输出为高电平,其它均为低电平。列设为下拉输入,上升沿触发中断。假如P15一行为高电平,其它均为低电平。按下S5则P10可以检测到上升沿。那么可以检测到是哪个按钮。但事实证明是不可以的,具体我也不知道为什么。总是有两行一直产生中断,导致我程序根本跑不下去。(😓)
但是在这里要注意,如果你误按下了两个开关,如S9和S13。那么相当于短路,瞬间产生大电流可能会烧掉板子,加个保护措施——在每个IO口前加个限流电阻(小一点,不要影响到下拉电阻的作用 1K左右即可)。
一个改进方法(真香)
想到之前的按键实验,一般只用到了两个按键,且加上适当延时后,按键精确性非常高。于是我想到了利用两个按键组成编码。如按键1按下为0,按键2按下为1。以不同的按键顺序组成不同的编码,既可以得到无数种状态。想法可行,试了一下还真可以(😊)
直接上程序吧。(我此次实验的编码长度为8位,可以表示256个按键(状态))
//// GPIO.c文件
#include <GPIO.h>
#include <delay.h>
u8 row = 0;
extern u8 push_time;
extern u8 code;
void GPIO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义结构体
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //优先级分组
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOG, GPIO_PinSource1); //映射外部中断通道
GPIO_EXTILineConfig(GPIO_PortSourceGPIOG, GPIO_PinSource2);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2; //PG1,PG2 用来接按键的,产生中断
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //直接上拉,外部可以不用接上拉电阻
GPIO_Init(GPIOG,&GPIO_InitStruct); //接一个更好
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //用来接灯
GPIO_Init(GPIOG,&GPIO_InitStruct);
//************EXIT_Init***************//
EXTI_InitStruct.EXTI_Line = EXTI_Line1|EXTI_Line2;

本文分享了作者在驱动STM32矩阵键盘过程中遇到的问题,通过改进采用编码方案,仅用两个按键实现键盘操作,避免了复杂的中断和状态检测。
最低0.47元/天 解锁文章





