基于STM32G431嵌入式学习笔记——三、KEY按键入门

news2024/10/7 8:20:40

一、按键在CubeXM里的配置

可以打开先前配置过LED的CubeMX,在其基础上进行按键的配置。
个人建议在这里先将原环境拷贝
在这里插入图片描述
更改副本文件夹名为LED_KEY_LCD
在这里插入图片描述
打开文件夹中的.ioc文件进行配置
在这里插入图片描述
在配置之前,我们先查阅产品手册了解按键的电路图,以便确定我们引脚的选择。
在这里插入图片描述因此我们需要将这四个引脚进行配置,模式为输入:
在这里插入图片描述
其他位置无需更改,配置完毕后单击右上角生成代码

二、配置按键的文件环境

1.打开keil环境,进行初始化编译

打开LED_KEY_LCD文件夹里的keil环境
在这里插入图片描述
在这里若感觉文件名不适,可以将其修改为与文件夹相同的名字。
在这里插入图片描述
打开环境,进行初始化编译
在这里插入图片描述

2.添加按键相关的.c .h文件
(1)新建文件

在这里插入图片描述命名为key.c,保存路径如下
在这里插入图片描述新建key.h头文件,保存路径如下
在这里插入图片描述

(2)将两文件与环境关联起来。

添加key.c文件进入环境,具体操作可参考基于STM32G431嵌入式学习笔记——二、LCD模块入门中有关于lcd.c文件的导入
在这里插入图片描述
可以发现key.c已经进入环境
在这里插入图片描述在该文件里输入#include “key.h”,保存后编译,实现.h文件与环境的关联
在这里插入图片描述

3.编写按键函数
(1)在key.h中

因为我们需要读取按键的状态,而按键的本质还是引脚数据的读取,因此我们需要用到读引脚信息的函数
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef GPIOx, uint16_t GPIO_Pin)
函数定义位于
stm32g4xx_hal_gpio.c的370行左右
在这里插入图片描述调用该函数需要使用的头文件也在
stm32g4xx_hal_gpio.c*中给了我们提示:
在这里插入图片描述因此我们key.h里一定要加上该头文件
在这里插入图片描述我们曾了解过,KEY按键与PA0 PB0 PB1 PB2这四个引脚相关(如下)
在这里插入图片描述因此我们要想读取这四个按键的状态,结合上面的读引脚函数应以如下方式调用:

HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);//key4
HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);//key3
HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);//key2
HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);//key1

借助宏定义表示四个按键的状态,提高代码可读性

#define KB1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define KB2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define KB3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define KB4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)

在这里插入图片描述头文件中还要包含我们想要书写的函数的声明,因此再添加相关函数的声明:
在这里插入图片描述

(2)在key.c中

第一个是普通按下的函数

#include "key.h"

char Key_Scan(void)
{
    static int count1,count2,count3,count4;//四个按键
    count1 = count2 = count3 = count4 = 0;
    char key_value = 0;//键值
    /* key1 */
    if(KB1 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB1 == 0)
        {
            count1++;
            if(count1 == 1)
            {
                key_value = 1;//键值为1
                while(KB1 == GPIO_PIN_RESET);//按键松开的效果
            }
        }
    }
    else
    {
        count1 = 0;//置零
    }
    /* key2 */
    if(KB2 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB2 == 0)
        {
            count2++;
            if(count2 == 1)
            {
                key_value = 2;//键值为2
                while(KB2 == GPIO_PIN_RESET);//按键松开的效果
            }
        }
    }
    else
    {
        count2 = 0;//置零
    }
    /* key3 */
    if(KB3 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB3 == 0)
        {
            count3++;
            if(count3 == 1)
            {
                key_value = 3;//键值为3
                while(KB3 == GPIO_PIN_RESET);//按键松开的效果
            }
        }
    }
    else
    {
        count3 = 0;//置零
    }
    /* key4 */
    if(KB4 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB4 == 0)
        {
            count4++;
            if(count4 == 1)
            {
                key_value = 4;//键值为4
                while(KB4 == GPIO_PIN_RESET);
            }
        }
    }
    else
    {
        count4 = 0;
    }
    return key_value;
}

第二个是要求既可以长按,又可以短按的按键函数。

char Key_Scan_CD(void)
{
    static int count1,count2,count3,count4;
    count1 = count2 = count3 = count4 = 0;
    char key_value = 0;
    /* key1 */
    if(KB1 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB1 == 0)
        {
            count1++;
            if(count1 > 70)//长按
            {
                key_value = 11;
            }
        }
    }
    else
    {
        if(count1 >=1 && count1<=50)//短按
            key_value = 1;
        count1 = 0;//恢复置零
    }
    /* key2 */
    if(KB2 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB2 == 0)
        {
            count2++;
            if(count2 > 70)//长按
            {
                key_value = 22;
            }
        }
    }
    else
    {
        if(count2 >=1 && count2<=50)//短按
            key_value = 2;
        count2 = 0;//恢复置零
    }
    /* key3 */
    if(KB3 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB3 == 0)
        {
            count3++;
            if(count3 > 70)//长按
            {
                key_value = 33;
            }
        }
    }
    else
    {
        if(count3 >=1 && count3<=50)//短按
            key_value = 3;
        count3 = 0;//恢复置零
    }
    /* key4 */
    if(KB4 == 0)
    {
        HAL_Delay(10);//去抖
        if(KB4 == 0)
        {
            count4++;
            if(count4 > 70)//长按
            {
                key_value = 44;
            }
        }
    }
    else
    {
        if(count4 >=1 && count4<=50)//短按
            key_value = 4;
        count4 = 0;//恢复置零
    }
    return key_value;
}

三、按键与LED的联动

编写程序实现以下功能:
短按key1——只有奇数灯全亮
短按key2——只有偶数灯全亮
短按key3——全亮
短按key4——全灭

1.编写灯光控制函数
(1)编写led.h
#include "stm32g4xx_hal.h"

/*灯光的亮/灭*/
#define ON	1
#define OFF	0
/*宏定义表示灯光编号*/
#define LED1		GPIO_PIN_8
#define LED2    	GPIO_PIN_9
#define LED3    	GPIO_PIN_10
#define LED4    	GPIO_PIN_11
#define LED5    	GPIO_PIN_12
#define LED6    	GPIO_PIN_13
#define LED7    	GPIO_PIN_14
#define LED8    	GPIO_PIN_15
#define LEDALL		GPIO_PIN_All
/*控制亮灯函数的声明*/
void Control_LED(uint16_t LED, uint8_t LED_Status);

(2)编写亮灯函数

led.c文件内容如下:

#include "led.h"

void Control_LED(uint16_t LED, uint8_t LED_Status)
{
    if(LED_Status == OFF)//灭灯
    {
        HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_SET);//设置端口引脚,标明已被占用
        HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
    }
    else //亮灯
    {
        HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_RESET);//清除端口引脚,则LED可以使用
        HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
    }
}

2.编写主函数

①记得添加#include" led.h"头文件
在这里插入图片描述②主函数中书写switch逻辑语句

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  LCD_Init();//LCD初始�?
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	Control_LED(LEDALL,0);
  while (1)
  {
		value = 0;
    value = Key_Scan();
    switch (value)
    {
      case 1://只有奇数灯亮
        Control_LED(LED1,1);
        Control_LED(LED3,1);
        Control_LED(LED5,1);
        Control_LED(LED7,1);
		Control_LED(LED2,0);
        Control_LED(LED4,0);
        Control_LED(LED6,0);
        Control_LED(LED8,0);
        break;
      case 2://只有偶数灯亮
        Control_LED(LED2,1);
        Control_LED(LED4,1);
        Control_LED(LED6,1);
        Control_LED(LED8,1);
        Control_LED(LED1,0);
        Control_LED(LED3,0);
        Control_LED(LED5,0);
        Control_LED(LED7,0);
        break;
      case 3://灯光全亮
        Control_LED(LEDALL,1);
        break;
      case 4://灯光全灭
        Control_LED(LEDALL,0);
        break;
    }
    // lcd_test();
  }
  /* USER CODE END 3 */
}
3.实验结果

在这里插入图片描述在这里插入图片描述在这里插入图片描述

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

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

相关文章

07-Nginx 日志管理及自动切割

Nginx 日志管理及自动切割 对于程序员、运维来说&#xff0c;日志非常得重要。通过日志可以查看到很多请求访问信息&#xff0c;及异常信息。Nginx 也提供了对日志的强大支持。 日志管理范围 首先&#xff0c;下面要讲的这些日志相关属性可以配置在任意模块。在不同的模块&…

如果我在初用tomcat时,是看到这篇tomcat架构解析,是不是就不会被说菜鸡了!

写在前面 tomcat作为一个中间件&#xff0c;相信绝大多数java程序员&#xff0c;多多少少都应该用到过吧。尤其是在springboot还未流行的时候&#xff0c;本地环境&#xff0c;没少跑tomcat服务吧&#xff1f; 我们一般都是直接使用&#xff0c;将我们的web服务&#xff0c;直…

疫情下跨越一万公里的友情:熊超与飒特电子哨兵的故事

在熊超&#xff08;化名&#xff09;家中&#xff0c;有一面照片墙&#xff0c;上面贴满了他在非洲工作十多年的剪影。这些照片整齐地摆放成一个心形&#xff0c;挂在客厅最显眼的位置。每当亲戚朋友来访&#xff0c;熊超都会为他们讲起自己援助非洲十余年发生的故事。 十多年…

【无标题】EXCEL实现刷题

实现的思路&#xff1a; 导入题库word文件导入到excel–>绑定随机事件选定考题。 word题库导入Excel表的代码如下&#xff1a; 整理题库结构&#xff08;添加题号&#xff0c;分离答案&#xff09; Public Sub numAdd() Dim rng As Range, RNG1 As Range With Sheet1 .[b1]…

linuex服务器中如何安装mysql数据库(一次性完成,包含远程连接)

大家好。我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 今天给大家介绍一下&#xff0c;如何在新服务器中安装mysql数据库&#xff0c;总是捣鼓服务器&#xff0c;每次都去网上查&#xff0c;次次都不一样&#xff0c;浪费好多时间&#xff0c;这次自己记录…

Imperceptible Backdoor Attack: From Input Space to Feature Representation 笔记

1. 论文信息 论文名称Imperceptible Backdoor Attack: From Input Space to Feature Representation作者Nan Zhong&#xff08;Fudan University&#xff09;会议/出版社IJCAI 2022pdf&#x1f4c4;在线pdf 本地pdf代码&#x1f4bb;pytorch概要文中提出了一种难以察觉的后门…

temporal shift module(TSM)

【官方】Paddle2.1实现视频理解经典模型 — TSM - 飞桨AI Studio本项目将带大家深入理解视频理解领域经典模型TSM。从模型理论讲解入手&#xff0c;深入到代码实践。实践部分基于TSM模型在UCF101数据集上从训练到推理全流程实现行为识别任务。 - 飞桨AI Studiohttps://aistudio…

2. Object中equals和toStirng 源码分析

文章目录1.equals方法2.重写equals方法为何一定要重写hashCode方法&#xff1f;2.1 反例演示3.toString方法4. 整型转二进制我们都知道Object是所有类的父类&#xff0c;那么它里面的一些方法你是否真的理解了呢&#xff1f; 下面我们就以源码为基础来学习这些看似简单的方法吧…

谷歌浏览器无法使用翻译功能的解决方案,谷歌浏览器无法翻译怎么办?谷歌浏览器右键翻译失效了?

如果你发现网站别的方案无效&#xff0c;请参考我的方案&#xff0c; 绝对有效&#xff01; 2022年起&#xff0c;突然发现谷歌浏览器的翻译功能无法使用了&#xff0c;既然发现问题&#xff0c;就要解决问题&#xff0c;按照下面的步骤一步一步来操作 首先下载最新版谷歌浏览…

[附源码]java毕业设计校园出入管理系统

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

【Lua基础 第4章】Lua的流程控制、#的作用、table的创建方式、table表常用方法、函数、多返回值、可变长参数

文章目录&#x1f4a8;更多相关知识&#x1f447;一、Lua 的流程控制&#x1f538;if语句&#x1f31f;代码演示&#x1f538;if...else 语句&#x1f31f;代码演示&#x1f538;if...elseif...else 语句二、#的作用三、table的创建方式四、table表的常用方法使用&#x1f539;…

标记肽Suc-AAPI-pNA、72682-77-0

标记肽Suc-AAPI-对硝基苯胺编号: 184433 中文名称: 标记肽Suc-AAPI-对硝基苯胺 英文名: Suc-Ala-Ala-Pro-Ile-pNA CAS号: 72682-77-0 单字母: Suc-AAPI-pNA 三字母: Suc-Ala-Ala-Pro-Ile-pNA 氨基酸个数: 4 分子式: C27H38O9N6 平均分子量: 590.63 精确分子量: 590.27 等电点(P…

使用MobaXterm tunneling访问集群(服务器)jupyter notebook

应用场景 想要在本地计算机C上使用高性能服务器上的计算节点运行jupyter notebook相关的代码。 高性能服务器上通常只有一个公网ip用于账户登陆管理&#xff0c;但有多个计算节点&#xff0c;需要使用公网IP通过SSH方式登入管理节点A&#xff0c;并使用SSH二次登陆计算节点B&…

CKKS同态加密方案初步学习

如论文标题所示&#xff0c;CKKS允许复数和实数运算&#xff0c;是一个近似精度计算的方案&#xff0c;也就是解密出来的明文和加密之前的明文不会完全一致。也就是采用丢失部分精度来换取较高的效率。 CKKS的核心是把加密噪声视为近似计算误差的一部分&#xff0c;也就是解密出…

Python项目一:pygname

1.安装pip install pygame 2.加载模块初始化&#xff1a;开始 import sys import pygamepygame.init() #初始化3.创建窗口 3.1pygame .display模块 作用&#xff1a;创建游戏窗口 常见的内置方法&#xff1a; 方法作用 pygame。display.init() 初始化display模块p…

C++11标准模板(STL)- 算法(std::partial_sort)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 排序一个范围的前 N 个元素…

阿里巴巴最新总结「百亿级别并发设计手册」GitHub收获70K标星

随着淘宝购物节和抖音直播平台带货的火热&#xff0c;大批促销活动涌现&#xff0c;「秒杀」这个词也越来越频繁地出现在我们的生活里。 除了那些头部的电商公司&#xff0c;某多、某东&#xff0c;还有各种街、某会、某品等&#xff0c;甚至是一些老牌的传统企业&#xff0c;…

Android持久化技术,好内存不如烂存储

Android持久化技术&#xff0c;好内存不如烂存储前言六、Android持久化技术&#xff0c;好内存不如烂存储6.1 持久化技术介绍6.2 简单文件存储方案6.3 SharedPreferences存储方案6.3.1 获取SharedPreferences对象的三种方式6.3.2 使用SharedPreferences对象存储和读取数据6.4 S…

Model Fusion of Heterogeneous Neural Networks via Cross-Layer Alignment论文阅读

论文地址点这里 一. 介绍 本文是针对异构的网络融合技术&#xff0c;是基于上一篇OTFusion的论文进行的工作&#xff0c;解决了神经元关联问题。当所有的网络都具有相同的架构时&#xff0c;OTFusion比普通平均算法有明显的改进。与其他基于平均的模型融合方法相比&#xff0…

如何制作一个实时在线显示评论

通过循环容器及数据表功能&#xff0c;制作一个发送评论实时显示的功能 效果展示 具体步骤 制作评论背景 制作评论样式 制作一个发送评论输入框 制作一个发送按钮 创建评论数据表 添加获取评论事件 创建发送评论触发器 数据绑定与设置 步骤分解 制作评论背景 拖拽 循环容器 到…