【正点原子STM32连载】第十三章 按键输入实验 摘自【正点原子】APM32F407最小系统板使用指南

news2025/1/25 9:02:15

1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html#

第十三章 按键输入实验

上一章中介绍了GPIO的输出模式,并用其控制LED的亮灭。在实际的应用尝尽中,还会需要使用到GPIO的输入模式,来获取外部的输入信号,例如获取按键的状态。通过本章的学习,读者将学习到GPIO作为输入模式的使用。
本章分为如下几个小节:
11.1 硬件设计
11.2 程序设计
11.3 下载验证

11.1 硬件设计
11.1.1 例程功能

  1. 按下KEY0按键可控制LED0状态翻转,按下KEY_UP按键可控制LED1翻转。
    11.1.2 硬件资源
  2. LED
    LED0 - PF9
    LED1 - PF10
  3. 按键
    KEY0 - PE4
    KEY_UP - PA0
    11.1.3 原理图
    本章实验使用的两个APM32F407最小系统板板载按键,分别为KEY0按键和KEY_UP按键,其于板载MCU的连接原理图,如下图所示:
    在这里插入图片描述

图11.1.3.1 按键与MCU的连接原理图
从上面的原理图中可以看出,KEY0按键和KEY_UP按键的一端连接到了电源正极,而另一端分别与MCU的PE4引脚和PA0引脚相连接,因此当任意一个按键被按下时,MCU对应的引脚都能够读取到高电平的状态,而当松开按键后,MCU对应的引脚读取到的电平状态却是是确定的,因此用于读取KEY0按键和KEY_UP按键的PE4引脚和PA0引脚不仅要配置为输入模式,还需要配置成下拉,使对应引脚在悬空时被下拉在电源负极。
11.2 程序设计
11.2.1 Geehy标准库的GPIO驱动
本章实验中要通过读取GPIO引脚的输入状态来判断按键是否被按下,以此来控制对应LED的状态翻转,因此对于判断按键的状态,需要以下几个步骤:
①:配置GPIO引脚为输入模式和下拉
②:读取GPIO引脚的输入状态
在Geehy标准库中对应的驱动函数如下:
①:配置GPIO引脚
请见第10.2.1小节中配置GPIO引脚的相关内容。
②:读取GPIO引脚输入电平
该函数用于读取GPIO引脚的输入电平(高电平或低电平),其函数原型如下所示:
uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin);
该函数的形参描述,如下表所示:
在这里插入图片描述

表11.2.1.1 函数GPIO_ReadInputBit()形参描述
该函数的返回值描述,如下表所示:
在这里插入图片描述

表11.2.1.2 函数GPIO_ReadInputBit()返回值描述
该函数的使用示例,如下所示:

#include "apm32f4xx.h"
#include "apm32f4xx_gpio.h"

void example_fun(void)
{
    uint8_t value;
    
    /* 读取PA0引脚输入电平 */
    value = GPIO_ReadInputBit(GPIOA, GPIO_PIN_0);
    
    if (value == BIT_SET)
    {
        /* Do something. */
    }
    else
    {
        /* Do something. */
    }
}

11.2.2 按键驱动
按键驱动主要就是读取GPIO引脚的输入状态,以此判断按键是否被按下,本章实验中,按键的驱动代码包括key.c和key.h两个文件。
根据原理图可知,应当将PE4引脚和PA0引脚配置为输入模式和下拉,并在需要读取KEY0按键(KEY_UP按键)状态的时候,读取PE4引脚(PA0引脚)的输入电平,若读取到PE4引脚(PA0引脚)的输入电平为高电平,则说明KEY0按键(KEY_UP按键)被按下,反之,则说明KEY0按键(KEY_UP按键)没有被按下。
按键驱动中,对引脚的定义,如下所示:

#define KEY0_GPIO_PORT			GPIOE
#define KEY0_GPIO_PIN			GPIO_PIN_4
#define KEY0_GPIO_CLK_ENABLE()								\
    do {														\
    		RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOE);	\
    } while (0)

#define WKUP_GPIO_PORT			GPIOA
#define WKUP_GPIO_PIN			GPIO_PIN_0
#define WKUP_GPIO_CLK_ENABLE()								\
    do {														\
    		RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);	\
    } while (0)

按键驱动中,操作引脚的定义,如下所示:

#define KEY0	GPIO_ReadInputBit(KEY0_GPIO_PORT, KEY0_GPIO_PIN)
#define WK_UP	GPIO_ReadInputBit(WKUP_GPIO_PORT, 

WKUP_GPIO_PIN)
按键驱动中,按键的初始化函数,如下所示:

/**
 * @brief	初始化按键
 * @param	无
 * @retval	无
 */
void key_init(void)
{
    GPIO_Config_T gpio_init_struct;
    
    /* 使能时钟 */
    KEY0_GPIO_CLK_ENABLE();
    WKUP_GPIO_CLK_ENABLE();
    
    /* 配置KEY0引脚 */
    gpio_init_struct.pin	= KEY0_GPIO_PIN;		/* KEY0引脚 */
    gpio_init_struct.mode	= GPIO_MODE_IN;			/* 输入模式 */
    gpio_init_struct.pupd	= GPIO_PUPD_DOWN;		/* 下拉 */
    GPIO_Config(KEY0_GPIO_PORT, &gpio_init_struct);	/* 配置KEY0引脚 */
    
    /* 配置KEY_UP引脚 */
    gpio_init_struct.pin	= WKUP_GPIO_PIN;		/* KEY_UP引脚 */
    gpio_init_struct.mode	= GPIO_MODE_IN;			/* 输入模式 */
    gpio_init_struct.pupd	= GPIO_PUPD_DOWN;		/* 下拉 */
    GPIO_Config(WKUP_GPIO_PORT, &gpio_init_struct);	/* 配置KEY_UP引脚 */
}
按键的初始化函数中,使能了KEY0按键和KEY_UP按键对应引脚的GPIO端口时钟,并将其配置为输入模式和下拉。
按键的驱动中,扫描按键状态的函数,如下所示:
/**
 * @brief	扫描按键
 * @note	该函数具有响应优先级(同时按下多个按键):KEY_UP > KEY0
 * @param	mode: 扫描模式
 * 	@arg 	不支持连按(当按键按下不放时,只有第一次调用会返回键值,
 * 			必须松开以后,再次按下才会返回其他键值)
 * 	@arg 	支持连续按(当按键按下不放时,每次调用该函数都会返回键值)
 * @retval	键值
 * 	@arg	KEY0_PRES: KEY0按下
 * 	@arg	WKUP_PRES: KEY_UP按下
 */
uint8_t key_scan(uint8_t mode)
{
    static uint8_t key_up = 1;					/* 按键松开标志 */
    uint8_t key_val = 0;
    
    if (mode == 1)								/* 支持连按 */
    {
    		key_up = 1;
    }
    
    /* 按键松开标志为1,且有按键按下 */
    if ((key_up == 1) && ((KEY0 == 1) || (WK_UP == 1)))
    {
    		key_up = 0;
    		delay_ms(10);							/* 去抖动 */
    		if (KEY0 == 1)
    		{
    			key_val = KEY0_PRES;
    		}
    		if (WK_UP == 1)
    		{
    			key_val = WKUP_PRES;
    		}
    }
    else if ((KEY0 == 0) && (WK_UP == 0))		/* 没有按键按下,标记按键松开 */
    {
    		key_up = 1;
    }
    
    return key_val;								/* 返回键值 */
}

以上函代码就实现了按键扫描,且具有按键消抖的功能。
11.2.3 实验应用代码
本章实验的应用代码,如下所示:

int main(void)
{
    uint8_t key;
    
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3);	/* 设置中断优先级分组为组3 */
    sys_apm32_clock_init(336, 8, 2, 7);					/* 配置系统时钟 */
    delay_init(168);										/* 初始化延时功能 */
    usart_init(115200);									/* 初始化串口 */
    led_init();											/* 初始化LED */
    key_init();											/* 初始化按键 */
    
    while (1)
    {
    		key = key_scan(0);		/* 扫描按键 */
    		
    		switch (key)
    		{
    			case KEY0_PRES:		/* KEY0被按下 */
    			{
    				LED0_TOGGLE();	/* LED0状态翻转 */
    				break;
    			}
    			case WKUP_PRES:		/* KEY_UP被按下 */
    			{
    				LED1_TOGGLE();	/* LED1状态翻转 */
    				break;
    			}
    			default:
    			{
    				break;
    			}
    		}
    		
    		delay_ms(10);
    }
}

可以看到应用代码中,在初始化完LED和按键后,就进入了一个while循环,在循环中,每间隔10毫秒就调用key_scan()函数扫描以此按键的状态,如果扫描到KEY0按键或KEY_UP按键被按下,则反转对应LED的亮灭状态。
11.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0和LED1默认是处于熄灭的状态,若此时按下并释放一次KEY0按键,则能够看到LED0的亮灭状态发生了一次翻转,同样的,若此时按下并释放一次KEY_UP按键,则能够看到LED1的亮灭状态发生了一次翻转,与预期的实验现象效果相符。

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

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

相关文章

高忆管理:低位缩量上涨说明什么?

在股票商场中,股票价格在低位缩量上涨是一种常见的走势。那么,低位缩量上涨究竟阐明了什么?本篇文章将从多个角度剖析,并给出全文摘要和3个关键词。 一、什么是低位缩量上涨? 低位缩量上涨是指股票价格在前期低点的邻…

jenkins同一jar包部署到多台服务器

文章目录 安装插件配置ssh服务构建完成后执行 没有部署过可以跟这个下面的步骤先部署一遍,我这篇主要讲jenkins同一jar包部署到多台服务器 【Jenkins】部署Springboot项目https://blog.csdn.net/qq_39017153/article/details/131901613 安装插件 Publish Over SSH 这…

angular中如何定义一个全局组件?

需求,我们需要新建一个navBreadcrumb的全局组件。这是一个面包屑导航,在不同的页面引入时传入一个路由数组即可。 第一步:我们新建这个组件: ng g c navBreadcrumb ng g m navBreadcrumb----------nav-breadcrumb.module-------…

文件和目录的基础操作

cat命令 concatenate(连接)的缩写,即 combine pieces together 1)把碎片组合在一起(意味着可以使用cat创建一个小文件) 2)显示文件 ──(root㉿kali)-[~] └─# cat /etc/resolv.conf # Generated by NetworkManager…

数字孪生和SCADA有哪些区别?

虽然SCADA和数字孪生用于工业领域,但它们有不同的用途。SCADA专注于工业过程的实时监测和控制,而数字孪生用于模拟和分析系统的性能。接下来,让我们详细讨论SCADA和数字孪生(SCADA与数字孪生)之间的区别。 SCADA与数字…

Python Opencv实践 - 图像仿射变换

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) rows,cols img.shape[:2] print(img.shape[:2])#使用getAffineTransform来获得仿射变换的矩阵M #cv.getAffineTransform(…

Java项目-苍穹外卖-Day04

公共字段自动填充 这些字段在每张表基本都有,手动进行填充效率低,且后期维护更改繁琐 使用到注解AOP主要 先答应一个AutoFill注解 再定义一个切面类进行通知 对应代码 用到了枚举类和反射 package com.sky.aspect; /*** 自定义切面类&#xff0c…

信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数)

信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数) 目录 应用背景相关知识操作步骤1、认识基本的初级函数2、相对引用,绝对引用,混合引用3、统计函数4、文本函数 应用背景 熟练掌握Excel的函数工具能让我们在日常的使用中更加方…

8.深浅拷贝和异常处理

开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题: 8.1 浅拷贝 首先浅拷贝和深拷贝只针对引用类型 浅拷贝:拷贝的是地址 常见方法: 1.拷贝对象:Object.assgin() / 展开运算符{…obj} 拷贝对象 2.拷贝数组:Array.prototype.con…

【小胡同志】我的创作纪念日——暨加入CSDN128天留念!

2023年4月12日,我首次加入CSDN这个创作大集体,大家庭!实属荣幸,倍感荣耀!在此之前,就曾听说,CSDN是中国开发者的摇篮,今日之悟,确有名之所属之感! 机缘 128天…

完美解决微信小程序使用复选框van-checkbox无法选中

由于小程序使用了vant-ui框架&#xff0c;导致checkbox点击无法选中问题 <van-checkbox value"{{ checked }}" shape"square"><view class"check-content"><view class"checktext">我已阅读并同意>《用户协议》…

中文医学知识语言模型:BenTsao

介绍 BenTsao&#xff1a;[原名&#xff1a;华驼(HuaTuo)]: 基于中文医学知识的大语言模型指令微调 本项目开源了经过中文医学指令精调/指令微调(Instruction-tuning) 的大语言模型集&#xff0c;包括LLaMA、Alpaca-Chinese、Bloom、活字模型等。 我们基于医学知识图谱以及医…

从其他地方复制的内容无法粘贴到idea中

问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 使用 idea 开发的时候&#xff0c;从其他地方复制的内容无法粘贴到 idea中&#xff0c;idea的版本是 2023.2 解决方案&#xff1a; 提示&#xff1a;这里填写该问题的具体解决方案&#xff1a; 网上查找资料…

文末有福利 | 小海小源表情包第一弹正式上线

手机铃声提醒你有新的消息 抓紧打个招呼“来了” 收到暖心的称赞 真是按捺不住激动的小心脏啊 只要你愿意拿起书 知识的大门将为你敞开 呲溜~ 这是不是像极了努力工作一天后下班的你&#xff1f; 。。。。。。 看了这么多“海源”表情包 是不是觉得小海、小源愈发可爱了呢…

“保姆级”考研下半年备考时间表

7月-8月 确定考研目标与备考计划 暑假期间是考研复习的关键时期&#xff0c;需要复习的主要内容有&#xff1a;重点关注重要的学科和专业课程&#xff0c;复习相关基础知识和核心概念。制定详细的复习计划并合理安排每天的学习时间&#xff0c;增加真题练习熟悉考试题型和答题技…

【ES6】箭头函数和普通函数的区别

它们之间的区别&#xff1a; &#xff08;1&#xff09;箭头函数没有自己的this。 &#xff08;2&#xff09;不可以当作构造函数&#xff0c;不可以对箭头函数使用new命令&#xff0c;否则抛出错误。 &#xff08;3&#xff09;不可以使用arguments对象&#xff0c;该对象在函…

今年全球智能手机出货量将创10年来新低 |百能云芯

据Counterpoint Research的最新报告称&#xff0c;本年度全球智能手机出货量可能面临十年来最低的局面。然而&#xff0c;值得注意的是&#xff0c;由于高端iPhone销售的坚挺表现&#xff0c;苹果有望在今年成为全球智能手机出货量的冠军。 需要强调的是&#xff0c;出货量并非…

【leetcode】225.用队列实现栈

分析&#xff1a; 队列遵循先入先出的原则&#xff0c;栈遵循后入先出的原则 也就是说&#xff0c;使用队列实现栈时&#xff0c;入队操作正常&#xff0c;但是出队要模拟出栈的操作&#xff0c;我们需要访问的是队尾的元素&#xff1b;题目允许使用两个队列&#xff0c;我们可…

ardupilot开发 --- 位置控制篇

几个疑问 如何根据GPS定位信息进行位置控制&#xff1f; 经纬度海拔高度如何转成导航坐标系&#xff1f; 飞控中的航迹点waypoint是基于那个坐标系的点&#xff1f;导航坐标系&#xff1f; Home点&#xff1f;导航坐标系的原点&#xff1f;电机解锁时的点&#xff1f;xyz&…

JTS多边形自相交异常问题处理

遇到一个奇怪的问题&#xff0c;线上某户型导入报了个异常com.vividsolutions.jts.geom.TopologyException: found non-noded intersection between LINESTRING。 看日志定位问题出在计算两柜体是否相交的方法上 Point middlePoint AlgorithmUtils.middlePoint(sp,ep); Poin…