STM32全部教程
:【STM32】标准库与HAL库对照学习系列教程大全
一、前言
本篇介绍关于如何使用STM32控制按键,并使用标准库与HAL库同时配置按键以增加您对按键的理解,希望对您有所帮助。 |
本篇讲解的是使用软件控制按键,关于使用中断控制按键,可以参考这篇文章:【STM32】标准库与HAL库对照学习教程五–外部中断详讲与配置
二、准备工作
- STM32开发板(我用的是普中的STM32F103ZE开发板)
- cubemx软件、keil 5(MDK)
- 开发板原理图
三、按键介绍
按键是一种电子开关,使用时按开关按钮,开关导通,当松开手时,开关断开。
由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。
抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。如下图所示
按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖。
按键消抖有两种方式,一种是硬件消抖,另一种是软件消抖。
- 硬件消抖:按键电路有过滤的电容,可以吸收不稳定的抖动信号。
- 软件消抖:通过软件延时一段时间,等抖动时间过去后再进按键状态判断,一般为5ms 到 10ms。
我的开发板没有过滤电容进行硬件消抖,所以我用的是软件消抖(一般也是用软件消抖)
四、硬件图
根据自己开发板的原理图来。
五、标准库控制按键
关于工程配置在我写的教程篇中已有详细介绍,这里不进行阐述,直接给出控制程序。
main.c
#include "LED.h"
#include "Delay.h"
#include "System.h"
#include "key.h"
/*************************************************
*函数名: main
*函数功能: 主函数
*输入: 无
*返回值: 无
**************************************************/
int main()
{
SysTick_Init(72);
LED_Init();
KEY_Soft_Init();
while(1)
{
Key = KEY_Scan(1);
switch(Key)
{
case NONE: break;
case key_up: LED_0 = !LED_0; break; //LED0电平翻转
case key0: LED_1 = 0; break; //LED1点亮
case key1: LED_1 = 1; break; //LED1熄灭
default :break;
}
}
}
key.c
#include "key.h"
#include "Delay.h"
#include "System.h"
/*************************************************
*函数名: KEY_Soft_Init
*函数功能: 按键初始化
*输入: 无
*返回值: 无
**************************************************/
void KEY_Soft_Init()
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(KEY_UP_RCC|KEY_RCC, ENABLE); //打开对应端口时钟
/************引脚初始化************/
GPIO_InitStruct.GPIO_Pin = KEY_UP_Pin; //WU_UP引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入模式
GPIO_Init(KEY_UP_GPIO_Port, &GPIO_InitStruct); //初始化引脚
GPIO_InitStruct.GPIO_Pin = KEY_Pin; //KEY1与KEY0引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //上拉输入模式
GPIO_Init(KEY_GPIO_Port, &GPIO_InitStruct); //初始化引脚
}
/*************************************************
*函数名: KEY_Scan
*函数功能: 按键扫描
*输入: Mode:1-支持连按,0-不支持连按
*返回值: key枚举类型,key_up:KEY_UP按键按下,Key1: KEY1按键按下 ,Key0: KEY0按键按下,NONE: 没有按键按下
**************************************************/
key KEY_Scan(u16 Mode)
{
static u16 KEY_Value = 1;
if(Mode == 1) KEY_Value = 1; //是否支持连按
if( KEY_Value == 1 && (KEY_UP == 1 || KEY1 == 0 || KEY0 == 0)) //如果有按键按下
{
KEY_Value = 0;
Delay_ms(10); //消抖
if(KEY_UP == 1) return key_up; //判断KEY_UP按键按下
else if(KEY1 == 0) return key1; //判断KEY1按键按下
else if(KEY0 == 0) return key0; //判断KEY0按键按下
else return NONE; //没有按键按下
}
else if(KEY_UP == 0 && KEY1 == 1 && KEY0 == 1) //没有按键按下时
KEY_Value = 1;
return NONE;
}
key.h
#ifndef KEY_H_
#define KEY_H_
#include "stm32f10x.h"
/************IO口宏定义便于移植************/
//引脚按键接高电平
#define KEY_UP_GPIO_Port GPIOA
#define KEY_UP_Pin GPIO_Pin_0
#define KEY_UP_RCC RCC_APB2Periph_GPIOA
//引脚按键接地
#define KEY_GPIO_Port GPIOE
#define KEY_Pin GPIO_Pin_3|GPIO_Pin_4
#define KEY_RCC RCC_APB2Periph_GPIOE
/************位带操作************/
#define KEY_UP PAin(0)
#define KEY1 PEin(3)
#define KEY0 PEin(4)
/************使用枚举将按键值化************/
typedef enum key
{
NONE = 0,
key_up = 1, //KEY_UP按键按下
key0 = 2, //KEY0按键按下
key1 = 3 //KEY1按键按下
}key;
static key Key; //枚举变量申明
/************函数申明************/
void KEY_Soft_Init(void); //按键初始化
key KEY_Scan(u16 Mode); //扫描函数
#endif
工程程序涉及位带与延时函数的知识,可以看这两文章理解:
【STM32】标准库与HAL库对照学习教程四–延时函数详解
六、HAL库控制按键
HAL库我们使用cubemx配置工程,相关配置操作在我写的教程篇中有详细说明,这里只放相关配置图,具体生成工程不再详细阐述。
①
②
③
④按键
⑤LED
⑥
⑦
程序
①
#include "System.h"
/*************************************************
*函数名: KEY_Scan
*函数功能: 按键扫描
*输入: Mode:0-间断模式,1-连按模式
*返回值: 1:KEY_UP按键按下
2:KEY1按键按下
3:KEY0按键按下
0:无按键按下
**************************************************/
uint16_t KEY_Scan(uint8_t Mode)
{
static uint8_t KEY_Value = 1;
if(Mode == 1) KEY_Value = 1; //判断是否为连按模式
if(KEY_Value == 1 && (PAin(0) == 1 || PEin(3) == 0 || PEin(4) == 0)) //有按键按下
{
KEY_Value = 0;
HAL_Delay(10); //延时消抖
if(PAin(0) == 1) return 1; //KEY_UP按键按下
else if(PEin(3) == 0) return 2; //KEY1按键按下
else if(PEin(4) == 0) return 3; //KEY0按键按下
else return 0; //无按键按下
}
else if(PAin(0) == 0 && PEin(3) == 1 && PEin(4) == 1) //无按键按下
KEY_Value = 1;
return 0;
}
②
switch(KEY_Scan(0))
{
case 0:break;
case 1:PBout(5) = !PBout(5); break; //LED0翻转电平
case 2:PEout(5) = 0; break; //LED1点亮
case 3:PEout(5) = 1; break; //LED1熄灭
default: break;
}
是不是和标准库差不多呀,只是IO口的配置交给了cubemx配置了。
关于想要更深入了解按键的使用,可以看这篇文章:
一个学妹写的按键检测函数把我秀翻了
挺高级的。
那么关于按键的使用到这里就结束啦!