STM32矩阵按键扫描冲突问题

最近做了一个项目,有个部分用到了矩阵扫描的原理,要检测按键是否按下去执行一个动作。一开始硬件工程师的原理图实现是设计成传统矩阵按键方式,大致原理如下所示:
在这里插入图片描述
这种硬件实现方式当去检测单个按下、一整行按下或一整列按下时是没有问题,但是我们同时按下s0、s1和s4的时候,问题就来了。在这里插入图片描述
当我们按下s0和s1的时候相应的第一行就会导通,结合列的上拉电阻便可检测出s0和s1按键被按下。但是!!!当我们s4按下时第二行也被导通了,并且随着s1按键的按下,第二列也是被导通。所以当我们按下s0、s1和s4按键时,s5按键就会被误检测成被按下,所以这是错误的。经过不懈的努力和查阅相关资料,对以上的电路进行了修改。
在这里插入图片描述
在每一个按键前面加上一个二极管进行阻隔,使得各按键不受列电流的影响,有了电路原理,代码按键扫描检测就简单多了。
先对按键GPIO进行定义,方便后续编写代码。

KEY ROW/
#define KEY_ROW_APB2PERIPH                (RCC_APB2Periph_GPIOA)
#define KEY_ROW_PORT                       GPIOA
#define KEY_ROW1_PIN                      GPIO_Pin_10
#define KEY_ROW2_PIN                      GPIO_Pin_11
#define KEY_ROW3_PIN                      GPIO_Pin_12
#define KEY_ROW4_PIN                      GPIO_Pin_15

KEY COL
#define KEY_COL_APB2PERIPH                (RCC_APB2Periph_GPIOB)
#define KEY_COL_PORT                       GPIOB
#define KEY_COL1_PIN                      GPIO_Pin_3
#define KEY_COL2_PIN                      GPIO_Pin_4
#define KEY_COL3_PIN                      GPIO_Pin_5
#define KEY_COL4_PIN                      GPIO_Pin_6

typedef struct gpio_group {
	GPIO_TypeDef *port;
	uint16_t pin;	
} GPIO_GROUP;

检测流程大致思路:将行的四个引脚作为输出引脚设置成开漏输出,列引脚直接设置成浮空状态。将输出引脚轮流拉低去再去检测每个按键输入引脚的状态。就是说,先将ROW1输出为0,然后当ROW1的某个按键被按下时,浮空引脚便会跟着被拉低就可以检测到输入引脚的高低电平。

static GPIO_GROUP GPIO_LKEY_ROW[4] = {
	{KEY_ROW_PORT, KEY_ROW1_PIN},
	{KEY_ROW_PORT, KEY_ROW2_PIN},
	{KEY_ROW_PORT, KEY_ROW3_PIN},
	{KEY_ROW_PORT, KEY_ROW4_PIN},
};

static GPIO_GROUP GPIO_KEY_COL[4] = {
	{KEY_COL_PORT, KEY_COL1_PIN},
	{KEY_COL_PORT, KEY_COL2_PIN},
	{KEY_COL_PORT, KEY_COL3_PIN},
	{KEY_COL_PORT, KEY_COL4_PIN},
};
/*******************初始化引脚***********************************/
void KEY_Init(void)
{
	//KEY ROW
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(KEY_ROW_APB2PERIPH,ENABLE);
	GPIO_InitStructure.GPIO_Pin = KEY_ROW1_PIN | KEY_ROW2_PIN |
	                              KEY_ROW3_PIN | KEY_ROW4_PIN ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;          
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(KEY_ROW_PORT, &GPIO_InitStructure);   
	
	//KEY COL
	RCC_APB2PeriphClockCmd(KEY_COL_APB2PERIPH,ENABLE);
	GPIO_InitStructure.GPIO_Pin = KEY_COL1_PIN | KEY_COL2_PIN|
	                              KEY_COL3_PIN | KEY_COL4_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(KEY_COL_PORT, &GPIO_InitStructure);                              
}
/*******************控制行输出电压***********************************/
//controller all row
static void activate_all_row(uint8_t status)
{
	int row;
	for (row = 0; row < 4; row++) 
	{
		if (status) 
		{
			GPIO_SetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
		} 
		else 
		{
			GPIO_ResetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
		}
	}
}

//controller  row
static void activate_row(uint8_t row, uint8_t status)
{
	if (status) 
	{
		GPIO_SetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
	} 
	else 
	{
		GPIO_ResetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
	}
}
/********************按键扫描***********************************/
void KEY_Scan(void)
{
	uint8_t row, col,keyScan[4][4]={0};
	activate_all_row(1)
	for(row = 0;row < 4; row ++)
	{
		activate_row(row, 0);
		delay_US(1);
		
		for(col = 0;col < 4;col ++)
		{
			if(GPIO_ReadInputDataBit(GPIO_KEY_COL[col].port,GPIO_KEY_COL[col].pin) == 0)
				keyScan[row][col] = 1;
		}
		activate_row(row, 1);
	}
	activate_all_row(1)
	for(row = 0;row < 4;row ++)
		for(col = 0;col < 4;col ++)
		{
			if(keyScan[row][col] != 0)
			printf("第%d个按键被按下\r\n",(row+1)*(col+1));
		}
}

以上就是矩阵按键扫描的整个思路流程,代码因为是博客上临时修改写的,不知道能不能编译通过,但是思路就是这么个思路,如果有大佬有更好的解决方案也可一起讨论。

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值