蓝桥杯物联网学习--3*2拓展键盘

本文讨论了使用STM32F4xx开发板的矩阵键盘,介绍了引脚分配、按键检测原理以及如何解决B3和B6按键的双击和键值反转问题,涉及GPIO配置、消抖代码和Cubemx配置要点。
摘要由CSDN通过智能技术生成

1,首先先要知道矩阵键盘的引脚,以下是按键与芯片引脚的关系,由于PA8引脚于oled屏幕连接,我个人感觉B3和B6按键的电气特性是要不同于另外四个引脚的。主要体现同一个代码,其他四个按键都没问题,但是B3和B6会出现双击或者键值相反的问题(我做了按键消抖)。

2,我是借鉴了gpt的代码,个人感觉代码写的很简洁,本来都搞不明白按键检测的原理,看过这个代码之后就懂了矩阵检测代码的原理。

#include "stm32f4xx_hal.h"

// 定义键盘矩阵的行和列
#define ROWS 2
#define COLS 3

// 定义矩阵键盘的GPIO引脚
GPIO_TypeDef* rows_GPIO_Port[ROWS] = {GPIOA, GPIOA};
uint16_t rows_Pin[ROWS] = {GPIO_PIN_0, GPIO_PIN_1};
GPIO_TypeDef* cols_GPIO_Port[COLS] = {GPIOB, GPIOB, GPIOB};
uint16_t cols_Pin[COLS] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2};

int scanKeyboard() {
    // 初始化GPIO引脚
    for (int i = 0; i < ROWS; i++) {
        HAL_GPIO_Init(rows_GPIO_Port[i], &GPIO_InitStruct);
        HAL_GPIO_WritePin(rows_GPIO_Port[i], rows_Pin[i], GPIO_PIN_RESET);
    }
    for (int j = 0; j < COLS; j++) {
        HAL_GPIO_Init(cols_GPIO_Port[j], &GPIO_InitStruct);
        HAL_GPIO_WritePin(cols_GPIO_Port[j], cols_Pin[j], GPIO_PIN_RESET);
    }

    // 扫描键盘状态
    for (int i = 0; i < ROWS; i++) {
        HAL_GPIO_WritePin(rows_GPIO_Port[i], rows_Pin[i], GPIO_PIN_SET);
        for (int j = 0; j < COLS; j++) {
            if (HAL_GPIO_ReadPin(cols_GPIO_Port[j], cols_Pin[j]) == GPIO_PIN_SET) {
                // 返回按下键的键值
                return i * COLS + j + 1;
            }
        }
        HAL_GPIO_WritePin(rows_GPIO_Port[i], rows_Pin[i], GPIO_PIN_RESET);
    }

    // 没有按键按下
    return 0;
}

int main() {
    // 初始化HAL库
    HAL_Init();
    // 配置GPIO引脚
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    for (int i = 0; i < ROWS; i++) {
        GPIO_InitStruct.Pin = rows_Pin[i];
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(rows_GPIO_Port[i], &GPIO_InitStruct);
    }
    for (int j = 0; j < COLS; j++) {
        GPIO_InitStruct.Pin = cols_Pin[j];
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(cols_GPIO_Port[j], &GPIO_InitStruct);
    }

    int key = scanKeyboard();
    // 处理按下的键值...
}

3,以下是我的代码,因为要用到串口调试,我还重写了一下打印函数。

#include "main.h"
#include "gpio.h"
#include "stdio.h"
#include "usart.h"

GPIO_TypeDef* row_GPIO_Port[2] = {GPIOB, GPIOB};
uint16_t row_Pin[2] = {GPIO_PIN_6, GPIO_PIN_7};
GPIO_TypeDef* col_GPIO_Port[3] = {GPIOB, GPIOB, GPIOA};
uint16_t col_pin[3] = {GPIO_PIN_1, GPIO_PIN_0, GPIO_PIN_8};

int scanKeyBorad(void)
{
	
	for (int i =0; i < 2; i ++)
	{
		HAL_GPIO_WritePin(row_GPIO_Port[i], row_Pin[i], GPIO_PIN_SET);
		HAL_Delay(40);				//按键消抖
		for (int j = 0; j < 3; j++)
		{
			if (HAL_GPIO_ReadPin(col_GPIO_Port[j], col_pin[j]) == GPIO_PIN_SET)
			{
				HAL_Delay(40);		//按键消抖
				return i * 3 + j + 1; 
			}
		}
		HAL_GPIO_WritePin(row_GPIO_Port[i], row_Pin[i], GPIO_PIN_RESET);
	}
	
	return 0;
}

int fputc(int ch, FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart2, temp, 1, 0xFF);
	return ch;
}

4,说一下大概思路,就是两行引脚PB6和PB7设为输出模式,竖着的三列引脚PB1,PB0和PA7设置为输入模式,首先将第一行的引脚就是PB6设为高电平,然后去读取列引脚的电平,如果第一行的某一个键被按下,就可以读到那个键的引脚为高电平,再通过 行数*3+列数+1 这个公式算出按键的键值(1到6)。

5,要注意的是cubemx的配置,除了选择输出输入模式外,还要讲GPIO Pull选择成我这样,三个输入的改成Pull-down,两个输出的选择为Pull-up。一定不能错这一步,不然按键就会疯狂的输出1

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值