STM32矩阵按键

news2024/12/26 21:04:56

矩阵按键原理

本实验使用STM32F103单片机,主题代码通用的。

如果每个按键占用一个GPIO引脚,对于使用多个按键来说就是一种资源的浪费,因此当我们在设计时,可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。
矩阵按键相对于独立按键稍微麻烦一点。4x4矩阵按键按照矩阵方式分别分为4行4列。主要有两种方式,一种是逐行扫描、一种是行列扫描。
原理图:
在这里插入图片描述

逐行扫描

通过在矩阵按键的每一条行线上轮流输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下。然后,根据当前输出低电平的行号和检测到低电平的列号组合,判断是哪一个按键被按下。

行列扫描

首先,在全部行线上输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下,并判断是哪一列有按键按下。
然后,反过来,在全部列线上输出低电平,检测矩阵按键的行线,当检测到的行线不全为高电平的时候,说明有按键按下,并判断是哪一行有按键按下。
最后,根据检测到的行号和检测的列号组合,以判断是哪一个按键被按下。

流程

矩阵按键程序实现

根据是国内棉矩阵按键电路图,编写矩阵按键应用程序,轮徇K1~K8按键动作,当对应的按键按下后,返回对应的值:

矩阵按键:
/************************************
按键表盘为: 1 2 3 10
4 5 6 11
7 8 9 12
13 0 14 15
/K1-K4(行)/
/K5-K8(列)/
/************************************
K1—>PC0
K2—>PC1
K3—>PC2
K4—>PC3
K5—>PC4
K6—>PC5
K7—>PC6
***********************************************************************/

编程要点

(1)使能LED灯和矩阵按键的GPIO时钟。调用函数:
RCC_AHB1PeriphClockCmd();
(2)编写矩阵按键扫描程序。
(3)同2-STM32GPIO输入之按键

矩阵按键初始化

/************************************************************************
 * @brief KEY_Config 按键初始化配置
 * @brief 列检测初始化
 * @param  无
 * @retval 无
 ***********************************************************************/

static void KEY_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    /*开启RCC时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    /*K1-K4(行)*/
    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    //设置引脚为
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    //设置引脚速度50MHZ
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /*K5-K8(列)*/
    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
    //设置引脚为推挽输出模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    //设置引脚速度50MHZ
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}

矩阵按键扫描程序

/************************************************************************
 * @brief KEY_4_4_Scan 扫描函数  矩阵按键扫描,返回一个键值
 * @brief 列检测初始化
 * @param  无
 * @retval uint8_t


***********************************
按键表盘为:  1   2  3   10
            4   5  6   11
            7   8  9   12
            13  0  14  15
************************************

矩阵按键:
    /************************************
按键表盘为:  1   2  3   10
            4   5  6   11
            7   8  9   12
            13  0  14  15
/************************************
        K1--->PC0
		K2--->PC1
		K3--->PC2
		K4--->PC3
		K5--->PC4
		K6--->PC5
		K7--->PC6
 ***********************************************************************/
uint8_t KEY_4_4_Scan(void)
{
    u8 KeyVal = 0;
    GPIO_Write(GPIOC, (GPIOC->ODR & 0xff00 | 0x000f)); // PC0-PC3全部输出高。
    if (((GPIOC->IDR & 0X00F0)) == 0x0000)             // PC4-PC7为0则没有按键按下(第一次检测按键是否有按下)
    {
        return 0xFF;
    }
    else
    {
        Delay_ms(10);                          //软件延时
        if (((GPIOC->IDR & 0X00F0)) == 0x0000) // PC4-PC7为0则没有按键按下(第二次检测按键是否有按下)
        {

            return 0xFF;
        }
    }
    GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0001)); //仅将PC0置高
    switch ((GPIOC->IDR & 0X00f0))                       //第一行,从PC4开始拉高,其余为0,PC5-PC7一样
    {
    case 0x0010:
        KeyVal = 1; // PC4
        break;
    case 0x0020:
        KeyVal = 2; // PC5
        break;
    case 0x0040:
        KeyVal = 3; // PC6
        break;
    case 0x0080:
        KeyVal = 10; // PC7
        break;
    }
    while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放,
        GPIO_Write(GPIOC, 0x0000);      //重新让PC0到PC3全部输出低。

    GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0002)); //仅将PC1置高
    switch ((GPIOC->IDR & 0X00F0))                       //第一行,从PC4开始拉高,其余为0,PC5-PC7一样
    {
    case 0x0010:
        KeyVal = 4;
        break;
    case 0x0020:
        KeyVal = 5;
        break;
    case 0x0040:
        KeyVal = 6;
        break;
    case 0x0080:
        KeyVal = 11;
        break;
    }
    while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放
        GPIO_Write(GPIOC, 0x0000);      //重新让PC0到PC3全部输出低。

    GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0004)); //仅将PC2置高
    switch ((GPIOC->IDR & 0X00F0))
    {
    case 0x0010:
        KeyVal = 7;
        break;
    case 0x0020:
        KeyVal = 8;
        break;
    case 0x0040:
        KeyVal = 9;
        break;
    case 0x0080:
        KeyVal = 12;
        break;
    }
    while (((GPIOC->IDR & 0X00F0)) > 0)
        GPIO_Write(GPIOC, 0x0000); //重新让PC0到PC3全部输出低。

    GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0008)); //仅将PC3置高
    switch ((GPIOC->IDR & 0X00F0))
    {
    case 0x0010:
        KeyVal = 13;
        break;
    case 0x0020:
        KeyVal = 0;
        break;
    case 0x0040:
        KeyVal = 15;
        break;
    case 0x0080:
        KeyVal = 16;
        break;
    }
    while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放
        GPIO_Write(GPIOC, 0x0000);      //重新让PC0到PC3全部输出低。

    return KeyVal;
}

主函数

int main(void)
{
  uint8_t Key_value = 0;
  // 来到这里的时候,系统的时钟已经被配置成72M。
  LED_Config();
  BEEP_Config();
  SysTick_InitUP(); //配置10us中断一次

  USART_Config();
  KEY_Init();
  //矩阵按键代码测试
  while (1)
  {
    Key_value = KEY_4_4_Scan();
    if (Key_value != 0xFF)
    {
      Delay_ms(200);
      printf("Key_value=%d\r\n", Key_value);
    }
    Delay_ms(200);
  }
}

实验现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go 语言搭建个人博客(qiucode.cn 重构篇 三)

1、读取配置文件 项目中如数据库连接、邮箱配置等这些信息一般会被写入一个文件,而通过编码在程序中读取想要的配置信息。 本项目使用yaml文件作为配置文件,配合第三方库viper来读取yaml配置文件。 go get -u github.com/spf13/viper在项目根目录新建一个yaml文件,内容如…

数学杂谈:限制条件下的均匀分布考察

数学杂谈:限制条件下的均匀分布考察 1. 问题描述2. 问题解答 1. 答案2. 解析3. 蒙特卡洛模拟 3. 离散情况延拓 1. 正整数的情况2. 整数的情况3. N→∞N \to \inftyN→∞的情况 4. 误区分析 1. 问题描述 假设x1,...,xnx_1, ..., x_nx1​,...,xn​均为0∼10 \sim 10…

思科防火墙解析(ASA)

♥️作者:小刘在C站 ♥️每天分享云计算网络运维课堂笔记,一起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放。 目录 一. 防火墙的分类, 二. 发展史, 三. 思科防火墙技术应用的…

[附源码]java毕业设计铁东社区新冠病毒疫苗接种管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

山东大学线性代数-4-线性方程组

目录 4.1 齐次线性方程组 4.1.1 齐次线性方程组的定义 4.1.2 方程组的三种形式 4.1.3 齐次线性方程组解的性质 4.1.4 行最简形矩阵 4.1.5 两个例题 4.2 基础解系的求法 4.2.1 求解步骤 4.2.2 例题 4.3 非齐次线性方程组 4.3.1 相关概念 4.3.2 非齐次线性方程组的有…

编译安装php扩展

1. 切换到要安装的扩展的目录下 2. 执行phpize(在扩展目录里 可以写自己电脑里的绝对路径) ../../bin/phpize 3. 然后执行 ./configure ./configure 4. 没问题的话 make 然后 make install make 运行之后出现下图就说明可以下一步了 运行 make install make install 出现…

GitHub使用教程

目录概要一. 下载git二. 初始化本地仓库设置签名查看状态,三大分区,添加,提交操作查看状态,三大分区添加查看提交历史查看提交历史的其他指令如何进行版本切换基于索引值基于^符号进行版本切换基于~符号进行版本切换reset指令的参…

【OS】新国立nus操作系统知识点(中文版)

文章目录1. Introduction to OS本章涉及1.1 什么是操作系统?1.2 为什么我们需要操作系统?抽象 Abstraction控制程序Summary1.3 现代操作系统分类1.4 操作系统结构OS结构OS是一个程序OS的实现单片OS Monolithic OS微核OS Microkernel虚拟机 Virtual Machi…

22071.11.20作业

在串口工具进行输入: echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led2灯点亮 echo 0 > /dev/myled1 ---->led2灯熄灭 echo 1 > /dev/myled2 ----&g…

项目实战——创建个人中心页面(上)

ps:本篇文章不涉及复杂代码编写,放心食用~~ 目录 一、整体框架 二、创建新表 bot 三、实现后端API 1、连接数据库和后端 2、实现 增删改查 API 1、增加一个 Bot 2、删除一个 Bot 3、修改一个 Bot 4、查询 Bot 列表 一、整体框架 二、创建新表 bo…

攻防世界nice_bgm

nice_bgm 题目描述:我拿出自己的私密音乐来和你分享,一起享受快乐吧 题目环境:https://download.csdn.net/download/m0_59188912/87097729 private bit隐写,直接用python脚本跑。 脚本源码: import re import binascii…

光线追踪与全域光渲染keyshot中文

keyshot可以快速、轻松地创神奇的渲染和动画效果,支持Mac和PC上的多种3D文件格式。它可以实时查看效果,使用方便,可以更快地创造视觉效果;材料超越了材料的外观,为高质量的视觉效果提供了科学准确的性能,使…

babel:无法将“babel“项目识别问题

全局安装babel命令 npm install --global babel-cli 局部安装babel命令 npm install --save-dev babel-cli 你安装后可能会出现的问题: 可能存在原因: ① 权限不够。 ②前面需改了node的global配置 --------------------------------------------…

i.MX 6ULL 驱动开发 二十三:UART

一、UART 协议 UART详解_sternlycore的博客-CSDN博客 二、UART 和 TTY 关系 基于Linux的tty架构及UART驱动详解 - 一口Linux - 博客园 (cnblogs.com) 三、Linux UART 驱动框架中重要对象 1、UART 驱动 struct uart_driver {struct module *owner;const char *driver_na…

python自动化之——获取钉钉群所有人的昵称

python自动化之——获取钉钉群所有人的昵称 楔子 精神小伙沙大柱入职了一家新公司,该公司所有成员都在钉钉群。 一天,沙大柱的上级沙小牛布置了任务:大柱,你把群里所有人的名称导出来吧,我不会操作。 大柱表示&…

【PyCharm中PIL/Pillow的安装】

🤵‍♂️ 个人主页老虎也淘气 个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏…

操作系统 - 进程

文章目录操作系统1.操作系统的定位2.进程2.1 PCB的一些属性2.3 进程调度相关属性 :本文小结操作系统 操作系统是一个软件   用途 :管理   1.对下 :管理硬键设备 2.对上 : 为软件提供稳定的运行环境 进一步来说 : 操作系统是软件…

多重背包问题

多重背包也是 0-1 背包的一个变式。与 0-1 背包的区别在于每种物品有ki个,而非一个。 一个很朴素的想法就是:把「每种物品选ki次」等价转换为「有ki个相同的物品,每个物品选一次」。这样就转换成了一个 0-1 背包模型,套用上文所述…

智慧民政解决方案-最新全套文件

智慧民政解决方案-最新全套文件一、建设背景二、建设思路三、建设方案四、获取 - 智慧民政全套最新解决方案合集一、建设背景 在城市信息化建设的大浪潮中,民政信息化建设关系就业、收入、教育、文体、健康、养老和社保等民间社会事务的管理与服务,在智…

Kettle运行Spoon.bat出现命令框然后闪退【BUG已解决】

文章目录项目场景:问题描述原因分析:解决方案:项目场景: 在内科大数据处理课程中,要求安装Kettle。 Kettle: Pentaho Data Integration以Java开发,支持跨平台运行,其特性包括&#…