STM32-按键检测

这篇具有很好参考价值的文章主要介绍了STM32-按键检测。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

做按键检测时,GPIO为输入操作

读取IO口输入电平调用的库函数为:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);

读取IO口输入电平操作的寄存器为:

GPIOx_IDR:端口输入寄存器

使用位带操作读取IO口输入电平:

PEin(4) -读取GPIOE.4口电平
PEin(n) -读取 GPIOE.n口电平

按键输入实验

1.使能按键对应IO口时钟。调用函数:RCC_APB2PeriphClockCmd();

2.初始化IO模式:上拉/下拉输入。调用函数:GPIO_lnit();

3.扫描IO口电平(库函数/寄存器/位操作)。

按键扫描(支持连续按)的实现思路

这个就是学51时最开始用的那个按键检测方法,简单

连续按意思是只要一直按住按键,按键就一直生效,比如增大音量键,按住不放,则音量会一直增加

如果要实现:按键按下,没有松开,只能算按下一次,这个函数无法实现。

u8 KEY_Scan(void)
{
	if(KEY被按下)
	{
		delay_ms(10);		//消抖
		if(KEY确实被按下)
		{
			return KEY_Value;
		}
		return 无效值;
	}
}

按键扫描(不支持连续按)的实现思路

不支持连续按意思就是,按下按键了,就算不松手,也只算按键被按下一次,必须松手后,再按下,才能算第二次按下,比如开启空调,按住电源键不放,也只是当作按下一次按键,不会说是连续按,电源开了又关,关了又开,不会这样设计

增加一个按下标志位key_up,按下后置0,只有当松手时才置1,要key_up和引脚状态同时为真才返回按键值

u8 KEY_Scan(void)
{
	static u8 key_up = 1;
	if(key_up && KEY被按下)
	{
		delay_ms(10);		//消抖
		if(KEY确实被按下)
		{
			key_up = 0;
			return KEY_Value;
		}
	}else if(KEY没有被按下){
		key_up = 1;
	}
	return 没有按下
}

支持连续按 和 不支持连续按 两者结合

在不支持连续按的代码上添加一句 if(mode == 1) key_up = 1;即可,可通过对传入的参数mode进行判断来实现两种按键方式的切换

如果mode == 1,则key_up = 1,则支持连续按;因为key_up被初始化为1,第一次按下时,if(key_up && KEY被按下)判断为真,检测KEY确实被按下后,key_up被置为0,返回 KEY_Value 然后return退出,假如是一直按着按键的,那下一次进行按键检测时,if(mode == 1) 为真,key_up = 1,所以 if(key_up && KEY被按下)判断又为真,继续进入里面执行,继续返回KEY_Value,达到连续按效果

如果mode != 1,则判断为假,key_up = 1不会执行,则这条 if 判断等于没有,代码就是上面不支持连续按的效果

u8 KEY_Scan(u8 mode)
{
	static u8 key_up = 1;
	if(mode == 1) key_up = 1;	//mode == 1,则支持连续按
	if(key_up && KEY被按下)
	{
		delay_ms(10);		//消抖
		if(KEY确实被按下)
		{
			key_up = 0;
			return KEY_Value;
		}
	}else if(KEY没有被按下)
	{
		key_up = 1;
	}
	return 没有被按下
}

所以要切换按键方式,在main函数while循环中调用KEY_Scan函数时,如果想支持连续按,则传入参数1,如果想不支持连续按,则传入参数不是1即可

void main()
{
	while(1)
	{
		KEY = KEY_Scan(1);	//支持连续按
		KEY = KEY_Scan(0);	//不支持连续按
        …………
	}
}

程序

KEY.h

定义两个按键状态的宏定义,声明函数

#ifndef _KEY_H_
#define _KEY_H_

#include "stm32f10x.h"

//按键状态宏定义
#define KEY_DOWN    0
#define KEY_UP      1

void KEY_Init(void);		//按键引脚初始化函数
u8   KEY_Scan(u8 mode);		//按键检测函数
#endif

KEY.c

要先对按键所接到的引脚进行初始化,配置为上拉输入,因为按键另一端接地,按键没按下时,引脚内部上拉电阻作用将引脚拉高,当按键被按下时,接GND,CPU读取引脚输入为低电平

按键扫描函数通过参数mode切换支持长按或不支持长按

#include "KEY.h"
#include "delay.h"

/**
  * @name   KEY_Init
  * @brief  按键初始化
  * @param  None
  * @retval None
  */
void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_Init_Structure;
    
    //先初始化GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    //配置GPIOA_Pin_8
    GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_8;          //按键接到了PA8引脚
    GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_IPU;      //设置为上拉输入

    //初始化PA8
    GPIO_Init(GPIOA,&GPIO_Init_Structure);
}

/**
  * @name   KEY_Scan
  * @brief  按键扫描
  * @param  mode:1:支持按键长按;其他:不支持按键长按
  * @retval u8
  */
u8 KEY_Scan(u8 mode)
{
    static u8 key_up = 1;
    //读取PA8引脚的值
    u8 KEY1 = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8);
    if(mode == 1) key_up = 1;
    //按键检测
    if(key_up && (KEY1 == 0))
    {
        delay_ms(10);           //消抖
        //确定按键按下
        if(KEY1 == 0)
        {
            key_up = 0;         //记录这次按下
            return KEY_DOWN;    //返回按下标志,0
        }
    }else if(KEY1 == 1){        //按键没按下或者松开
        key_up = 1;    
    }
    return KEY_UP;              //返回没按下标志,1
}

main.c

主函数while循环不断检测按键扫描函数,检测到函数返回按键按下标志后,执行亮灯操作

这里使用预编译指令,#ifndef #endif 和 #ifdef #endif,用宏定义KEY_MODE来进行支持长按和不支持长按的切换,这样就不用注释一大块的函数功能,只需注释宏定义语句就行了

当宏定义了KEY_MODE时,编译支持长按的语句;当注释掉宏定义了KEY_MODE时,编译不支持长按的语句

#include "LED.h"
#include "delay.h"
#include "KEY.h"

#define KEY_MODE 1


int main()
{
	LED_Init();		//LED初始化
	delay_init();	//延时初始化
	KEY_Init();		//按键初始化

	while(1)
	{
		#ifndef KEY_MODE
			//不支持长按
			if(KEY_Scan(0) == KEY_DOWN)
			{
				//GPIO_ResetBits(GPIOA,GPIO_Pin_1);	//点亮LED
				GPIOA->ODR ^= (0x01<<1);	//对ODR1进行异或取反操作,按一次点亮,再按一次熄灭
			}
		#endif

		#ifdef KEY_MODE
			//支持长按
			if(KEY_Scan(1) == KEY_DOWN)
			{
				GPIOA->ODR ^= (0x01<<1);	//对ODR1进行异或取反操作,按一次点亮,再按一次熄灭
				delay_ms(1000);
			}
		#endif
	}
}

想实现按一次按键亮灯,再按一次就灭灯,这个实现简单,只要把LED的引脚电平翻转即可,但查看了GPIO标准库相关函数发现好像没有让引脚电平翻转的函数,下面是各个函数的功能

STM32-按键检测

然后通过对寄存器进行操作,采用异或的功能,取反某一位,达到按一次亮,再按一次熄灭的效果

GPIOA->ODR ^= (0x01<<1);	//对ODR1进行异或取反操作,按一次点亮,再按一次熄灭

复习状态机用法

KEY.h

在KEY.h头文件中添加状态机的枚举类型,定义枚举类型变量STA_KEY,并用extern声明为外部变量

#ifndef _KEY_H_
#define _KEY_H_

#include "stm32f10x.h"

//按键状态宏定义
#define KEY_DOWN    0
#define KEY_UP      1

//状态机按键枚举类型
typedef enum
{
    KEY_Statues1,
    KEY_Statues2
}STA_KEY_t;

//定义变量
extern STA_KEY_t STA_KEY;

void KEY_Init(void);		//按键引脚初始化函数
u8   KEY_Scan(u8 mode);		//按键检测函数

void STA_KEY1(void);        //状态机,按键状态1
void STA_KEY2(void);        //状态机,按键状态2

#endif
KEY.c

源文件中添加不同状态要执行的函数,状态1按一次按键LED灯亮1秒再熄灭,然后切换到状态2,状态2中按一次按键LED灯亮1秒再熄灭,然后再亮1秒再熄灭,最后再把状态切回到状态1

/**
  * @name   STA_KEY1
  * @brief  状态机-按键状态1
  * @param  None
  * @retval None
  */
 void STA_KEY1()
 {
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);   //PA1置0,LED点亮
    delay_ms(1000);
    GPIO_SetBits(GPIOA,GPIO_Pin_1);     //延时1秒后熄灭LED灯
    delay_ms(1000);

    //切换状态
    STA_KEY = KEY_Statues2;
 } 

 /**
  * @name   STA_KEY2
  * @brief  状态机-按键状态2
  * @param  None
  * @retval None
  */
 void STA_KEY2()
 {
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);   //PA1置0,LED点亮
    delay_ms(1000);
    GPIO_SetBits(GPIOA,GPIO_Pin_1);     //延时1秒后熄灭LED灯、
    delay_ms(1000);

    GPIO_ResetBits(GPIOA,GPIO_Pin_1);   //PA1置0,LED点亮
    delay_ms(1000);
    GPIO_SetBits(GPIOA,GPIO_Pin_1);     //延时1秒后熄灭LED灯
    delay_ms(1000);

    //切换状态
    STA_KEY = KEY_Statues1;
 } 
main.c

主函数中当按键按下后,再用switch case 语句判断状态,并调用不同状态下的函数文章来源地址https://www.toymoban.com/news/detail-459211.html

#include "LED.h"
#include "delay.h"
#include "KEY.h"

#define KEY_MODE 1
STA_KEY_t STA_KEY;	//定义状态变量

int main()
{
	LED_Init();		//LED初始化
	delay_init();	//延时初始化
	KEY_Init();		//按键初始化

	while(1)
	{
		#ifndef KEY_MODE
			//不支持长按
			if(KEY_Scan(0) == KEY_DOWN)
			{
				//GPIO_ResetBits(GPIOA,GPIO_Pin_1);	//点亮LED
				//GPIOA->ODR ^= (0x01<<1);	//对ODR1进行异或取反操作,按一次点亮,再按一次熄灭

				//状态机点灯
				switch (STA_KEY)
				{
					case KEY_Statues1:STA_KEY1();break;
					case KEY_Statues2:STA_KEY2();break;
					default:STA_KEY = KEY_Statues1;break;
				}
			}
		#endif

		#ifdef KEY_MODE
			//支持长按
			if(KEY_Scan(1) == KEY_DOWN)
			{
				GPIOA->ODR ^= (0x01<<1);	//对ODR1进行异或取反操作,按一次点亮,再按一次熄灭
				delay_ms(1000);
			}
		#endif
	}
}

到了这里,关于STM32-按键检测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32速成笔记—按键检测

    🎀 文章作者:二土电子 🌸 关注文末公众号获取其他资料和工程文件! 🐸 期待大家一起学习交流! 按键检测原理比较简单,按键按下和不按下,其连接引脚的电平是不一样的,按键检测正是通过检测按键引脚的电平变化来实现的。比如按键未按下时引脚电平为高电平,按

    2024年02月08日
    浏览(51)
  • STM32CubeMX教程3 GPIO输入 - 按键响应

    开发板(STM32F407G-DISC1) STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 使用STM32CubeMX软件配置STM32F407开发板的按键作为输入,利用按键输入使LED灯产生响应 对于所有的GPIO来说都是既可以作为输出引脚也可以作为输入引脚使用,本开发板上有一个用户按键,

    2024年02月03日
    浏览(62)
  • STM32矩形(矩阵)按键(键盘)输入控制LED灯 ——4*4矩阵按键源码解析

    本文基于标准函数库的工程实现stm32F103C8T6使用4*4的矩阵按键控制LED灯的亮灭及闪烁等功能。 程序源码:链接:https://pan.baidu.com/s/1_MPhvMduKCTP0MPG-Gtw3A?pwd=2syk  提取码:2syk 文章目录 一、矩形键盘介绍 1、硬件电路基本原理 2、两种识别方法介绍 3、硬件接线即使用 二、程序源码

    2024年02月04日
    浏览(47)
  • STM32F103C8T6 按键扫描输入

    第一章 STM32F103C8T6 点亮LED灯 系列文章目录 前言 一、原理  1.按键类型  2.按键消抖 3.IO口输入配置 1)模拟输出 2)浮空输入模式 3)下拉输入模式(PULL DOWN) 4)上拉输入模式(PULL UP) 二、代码部分 main.c key.c key.h 总结         上一章我们成功入门了STM32F103C8T6,今天我们来

    2023年04月23日
    浏览(78)
  • 初学者思路-实现独立按键检测(以STM32为例)

            本文以初学者角度切入,详细剖析按键检测原理,实现按键短按、短按抬起、首次长按、持续长按次数、长按抬起功能; 目录 前言 波形图分析 抖动原因 为什么要消抖 如何消抖 原理图分析 程序设计思路 代码实践 按键配置 按键检测 实验结果 留下反思         如

    2024年01月16日
    浏览(57)
  • 【正点原子STM32连载】第十一章 按键输入实验 摘自【正点原子】APM32E103最小系统板使用指南

    1)实验平台:正点原子APM32E103最小系统板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 上一章中介绍了GPIO的输出模式,并用其控制LED的亮灭。在实际的应用尝尽中,还会需要使用到GPIO的

    2024年02月04日
    浏览(61)
  • STM32 -- 实现按键的长按与短按检测(其他单片机可移植)

    目录 资源获取 一 前言 二 思路  三 实现代码 1.主要代码 四 完整代码 Key.h Key.c 该改进版本(1ms太繁琐了,我改成了25ms检测一次)   1.定时器部分 2.按键检测部分  五、参考 欢迎关注微信公众号--星之援工作室 发送(长短按检测) 今天在逛博客的时候,偶然看到了一

    2024年02月12日
    浏览(40)
  • 正点原子STM32F103精英版+HAL库实现4×4矩阵按键检测

    首先声明,本人小白一枚,所做的工作都是借鉴网上的大佬+自己摸索,但是都是亲测实际有效的。 因为所需要的功能开发板自带按键不够用,所以购买了4×4矩阵按键,当时购买的时候以为一个按键对应一个IO口,后来发现不是这样的,会浪费太多的IO口,4×4矩阵键盘用8个

    2024年02月06日
    浏览(59)
  • golang读取键盘功能按键输入

    golang读取键盘功能按键输入 需求 最近业务上需要做一个终端工具,能够直接连到docker容器中进行交互。 技术选型 docker官方提供了python sdk、go sdk和remote api。 https://docs.docker.com/engine/api/sdk/ 因为我们需要提供命令行工具,因此采用golang进行开发。 遇到的问题 通过sdk可以正常和

    2024年02月09日
    浏览(40)
  • 物联网|按键实验---学习I/O的输入及中断的编程|读取I/O的输入信号|中断的编程方法|轮询实现按键捕获实验-学习笔记(13)

    1按键功能及用途,常见按键举例 2按键的工作原理 3按键的电路表示 课后小作业: 请大家课后百度现在流行的触摸式按键的相关信息,并考虑如何使用我们开发板的CPU如何操作触摸按键。 了解STM32F407中IO输入信号读取的原理. 了解STM32F407中外部中断的原理 .学习利用CMSIS实现I

    2024年02月14日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包