GD32零基础教程第四节(按键控制LED灯)

2024-04-09 00:52

本文主要是介绍GD32零基础教程第四节(按键控制LED灯),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、按键电路图分析及控制原理
  • 二、按键控制LED灯代码编写
  • 三、模块化封装按键代码
  • 总结


前言

本篇文章将带大家来学习按键的使用,按键其实也就是GPIO的控制,只不过按键的使用需要将GPIO配置为输入模式。

一、按键电路图分析及控制原理

在单片机中,按键通常用于实现用户交互和控制功能。

按键元件:

按键通常由一个机械开关组成,当按键被按下时,开关闭合,允许电流流过。

在板子上有一个用户按键,可供用户使用。

根据原理图可知这个按键接到了PA0引脚,当按键被按下时WK_UP接到了VCC,所以当按键被按下时表现为高电平,但是按键没有被按下时电平状态是不确定的。

所以这里需要接入下拉电阻,下面是接下拉电阻的原因:

稳定的逻辑状态:

当按键未被按下时,输入端口需要保持一个确定的逻辑状态,以确保系统正确地读取输入信号。接下拉电阻将输入端口连接到地(GND),使得在按键未被按下时,输入端口被拉低到逻辑低电平(0),从而保持稳定的逻辑状态。
防止悬空状态:

如果没有接下拉电阻,当按键未被按下时,输入端口将处于悬空状态,容易受到外部环境的干扰而导致不确定的电平状态。这可能导致系统误判按键状态,引发错误的操作或行为。

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

二、按键控制LED灯代码编写

1.使能对应的GPIO引脚:

rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOA时钟

2.将GPIO引脚设置为输入模式,并且设置一个下拉电阻:

gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);

3.读取GPIO引脚的状态:

FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)

函数参数:
gpio_periph:要操作的GPIO外设,通常是使用宏定义指定的GPIOx(x表示具体的GPIO端口,如GPIOA、GPIOB等)。
pin:要获取状态的GPIO引脚,通常是使用宏定义指定的引脚编号(如GPIO_PIN_0、GPIO_PIN_1等)。

返回值:
FlagStatus类型,是一个枚举类型,可能的取值有:
RESET:表示引脚未置位,即为低电平状态。
SET:表示引脚被置位,即为高电平状态。

具体代码:

#include "gd32f4xx.h"//包含了该系列芯片的寄存器定义、常量定义和函数声明等信息
#include "gd32f4xx_libopt.h"//GD32F4 系列芯片的外设库选项配置文件
#include "systick.h"//配置和使用 SysTick 定时器的功能文件#include "led.h"static int flag = 0;//定义一个变量来表示LED灯当前的状态int main(void)
{systick_config();//配置系统主频168M,外部8M晶振,配置在#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL        (uint32_t)(168000000)LED_Init();//初始化LED灯模块LED_OFF();//关闭LED灯rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOA时钟gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);//PA0配置成下拉输入	while(1){if(1 == gpio_input_bit_get(GPIOA, GPIO_PIN_0)){delay_1ms(10);//延时消抖if(1 == gpio_input_bit_get(GPIOA, GPIO_PIN_0)){flag = !flag;//翻转LED灯电平状态if(flag == 1){LED_ON();//点亮LED灯}else if(flag == 0){LED_OFF();//关闭LED灯}}}}
}

这里主要需要讲解的就是这个延时消抖部分:

按键需要延时消抖是因为机械按键在按下或释放的过程中会产生短暂的电气接触和断开,导致在按键信号上出现不稳定的波动。这种波动称为按键抖动(Bouncing),可能会导致系统误判按键操作,认为按键被按下了多次或产生了错误的按键事件。因此,需要延时消抖来确保稳定地检测按键状态。

按键被按下的理想状态:

在这里插入图片描述

按键被按下的实际状态:

在这里插入图片描述

三、模块化封装按键代码

在HardWare文件夹中创建key.c和key.h两个文件来保存按键的代码:

key.c:

/*** @file    key.c* @brief   KEY功能函数实现文件* @author  花落已飘* @date    2024-04-08*/#include "key.h"
#include "systick.h" // 包含用于延时的头文件/*** @brief 初始化按键* @note  使能按键对应 GPIO 端口的时钟,并设置按键引脚为输入模式,并启用下拉电阻*/
void KEY_Init(void)
{KEY_PORT_CLK_EN(); // 使能按键对应 GPIO 端口的时钟gpio_mode_set(KEY_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, KEY_PIN); // 设置按键引脚为输入模式,并启用下拉电阻
}/*** @brief 获取按键状态* @note  如果按键被按下,进行延时消抖后再次检测按键状态* @return 按键状态,KEY_PRESS 表示按键被按下,KEY_RELEASE 表示按键未被按下*/
int GetKeyStatus(void)
{KEY_STATUS key_status = KEY_RELEASE; // 初始化按键状态为释放状态if (1 == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) // 如果检测到按键被按下{delay_1ms(10); // 延时消抖,等待按键稳定if (1 == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) // 再次检测按键状态{key_status = KEY_PRESS; // 如果按键仍然处于按下状态,则更新按键状态为按下}else{key_status = KEY_RELEASE; // 如果按键已经释放,则更新按键状态为释放}}return key_status; // 返回按键状态
}

key.h:

#ifndef KEY_H
#define KEY_H#include "gd32f4xx.h"        // 包含了该系列芯片的寄存器定义、常量定义和函数声明等信息
#include "gd32f4xx_libopt.h" // GD32F4 系列芯片的外设库选项配置文件#define KEY_PORT     GPIOA     // 按键所在的 GPIO 端口
#define KEY_PIN      GPIO_PIN_0 // 按键所在的引脚编号
#define KEY_CLOCK    RCU_GPIOA // 按键对应的时钟使能#define KEY_PORT_CLK_EN()  rcu_periph_clock_enable(KEY_CLOCK) // 使能按键对应 GPIO 端口的时钟typedef enum
{KEY_PRESS = 0,   // 按键被按下KEY_RELEASE      // 按键未被按下
} KEY_STATUS;         // 定义按键状态枚举类型/*** @brief 初始化按键 GPIO 端口* @note  初始化按键所在的 GPIO 端口为输入模式,并设置上下拉电阻为下拉*/
void KEY_Init(void);/*** @brief 获取按键状态* @note  如果按键被按下,进行延时消抖后再次检测按键状态* @return 按键状态,KEY_PRESS 表示按键被按下,KEY_RELEASE 表示按键未被按下*/
int GetKeyStatus(void);#endif

main.c中调用:

#include "gd32f4xx.h"//包含了该系列芯片的寄存器定义、常量定义和函数声明等信息
#include "gd32f4xx_libopt.h"//GD32F4 系列芯片的外设库选项配置文件
#include "systick.h"//配置和使用 SysTick 定时器的功能文件//硬件初始化代码
#include "led.h"
#include "key.h"static int flag = 0;//定义一个变量来表示LED灯当前的状态int main(void)
{systick_config();//配置系统主频168M,外部8M晶振,配置在#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL        (uint32_t)(168000000)LED_Init();//初始化LED灯模块KEY_Init();//初始化KEY按键模块LED_OFF();//关闭LED灯while(1){if(KEY_PRESS == GetKeyStatus()){flag = !flag;if(flag == 1){LED_ON();}else if(flag == 0){LED_OFF();}}}
}

总结

本篇文章就讲解到这里,主要是按键的输入模式的使用。

但是在这里代码还是有非常多不足的地方,比如延时会阻塞程序的运行,降低CPU的执行效率。

以及没有及时的读取按键的数据导致数据的丢失等问题,后面的文章也会讲解到解决这些问题的方法。

链接:https://pan.baidu.com/s/10J6bdHrFWlSY-SFLW8hlNw
提取码:abvi

这篇关于GD32零基础教程第四节(按键控制LED灯)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/886803

相关文章

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

Spring Security注解方式权限控制过程

《SpringSecurity注解方式权限控制过程》:本文主要介绍SpringSecurity注解方式权限控制过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、摘要二、实现步骤2.1 在配置类中添加权限注解的支持2.2 创建Controller类2.3 Us

Python中如何控制小数点精度与对齐方式

《Python中如何控制小数点精度与对齐方式》在Python编程中,数据输出格式化是一个常见的需求,尤其是在涉及到小数点精度和对齐方式时,下面小编就来为大家介绍一下如何在Python中实现这些功能吧... 目录一、控制小数点精度1. 使用 round() 函数2. 使用字符串格式化二、控制对齐方式1. 使用

Springboot控制反转与Bean对象的方法

《Springboot控制反转与Bean对象的方法》文章介绍了SpringBoot中的控制反转(IoC)概念,描述了IoC容器如何管理Bean的生命周期和依赖关系,它详细讲解了Bean的注册过程,包括... 目录1 控制反转1.1 什么是控制反转1.2 SpringBoot中的控制反转2 Ioc容器对Bea