前言
上一篇文章已经介绍了如何实现流水灯,实现了点灯的第一步。这一篇则介绍按键控制点灯的实现过程。
一、实验原理
1.GPIO输操作说明
按键的初始化与LED灯初始化不同,LED是推挽输出,而按键则是输入。而输入也分两种:上拉输入和下拉输入。若是按键为共阴极,则按键按下时,IO口输入为低电平,需要在IO口接上拉电阻,则使用上拉输入模式;若是按键为共阳极,则按键按下时,IO口输入为高电平,需要在IO口接下拉电阻,则使用下拉输入模式。
其余根据板子的实际情况选择定时器,选择IO口即可。
二、实验步骤
1.按键消抖
因为按键是机械开关,在按下的时候会产生电平的抖动。可以采用延时消抖的方法,通过延时一小段时间,消除抖动。当然除了软件消抖还有硬件消抖的方法,可以看下下面这个链接【单片机】按键消抖及原理(硬件和软件方法详解)-CSDN博客
if(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL){ }
/* 按键扫描完毕,返回按键被按下状态 */
return KEY_DOWN;
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
2.长短按
为了检测按下时间的长短,可以采取延时计数的方法。通过引入时间计数的KeyTimeCount,在按键扫描的时候以延时多少时间,增大KeyTimeCount。最后自定义判断时间长短。
值得注意的是,要是想检测按下的时间更为精确,需要调整延时函数,且针对不同单片机的定时器有不同的频率,需要根据实际情况自行调整。
uint16_t KeyTimeCount = 0;
/* 等待按键弹开才退出按键扫描函数 */
while(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 时间计数 */
Delay(10);
KeyTimeCount = KeyTimeCount + 1;
}
/* 按键扫描完毕,返回按键被按下状态 */
if (KeyTimeCount <= 99) // 小于等于1s
{
/* 计数清零 */
KeyTimeCount = 0;
return KEY_DOWN; // 短按状态
}
else if (KeyTimeCount >= 199) // 大于等于2s
{
/* 计数清零 */
KeyTimeCount = 0;
return KEY_DOWN_LONG; // 长按状态
}
3.联合点灯
按键部署完后,就是一个联合点灯的过程,将bsp_led.h引入到bsp_key.c,便可以通过按键实现点灯了!(其实是灭灯)
void KEY_LED(void)
{
/* 读取按键状态 */
int key1State = KEYx_Choice(1);
/* 短按按键1 */
if (key1State == 1)
{
LED1_OFF;
}
}
三、实操代码
程序分为3个文件:bsp_key.c、bsp_key.h、main.c
1.bsp_key.c
/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/key/bsp_key.h"
void KEY_GPIO_Init(void)
{
/* 定义IO硬件初始化结构体变量 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能(开启)KEY引脚对应IO端口时钟 */
RCC_APB2PeriphClockCmd(KEY1_RCC_CLOCKGPIO|KEY2_RCC_CLOCKGPIO|KEY3_RCC_CLOCKGPIO, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 设定KEY对应引脚IO编号 */
GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN |KEY2_GPIO_PIN | KEY3_GPIO_PIN;
/* 配置KEY GPIO:输入上拉模式 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY3_GPIO, &GPIO_InitStructure);
GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
GPIO_Init(KEY2_GPIO, &GPIO_InitStructure);
}
/**
* 函数功能: 读取按键KEYx的状态
* 输入参数:无
* 返 回 值: KEY_UP :按键没被按下;
* KEY_DOWN:按键被按下;
* KEY_DOWN_LONG :按键被长按下
* 说 明:无。
*/
KEYState_TypeDef KEYx_StateSet(GPIO_TypeDef* KEYx_GPIO, uint16_t KEYx_GPIO_PIN, uint8_t KEYx_DOWN_LEVEL)
{
uint16_t KeyTimeCount = 0;
if(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(GPIO_ReadInputDataBit(KEYx_GPIO, KEYx_GPIO_PIN)==KEYx_DOWN_LEVEL)
{
/* 时间计数 */
Delay(10);
KeyTimeCount = KeyTimeCount + 1;
}
}
/* 按键扫描完毕,返回按键被按下状态 */
if (KeyTimeCount <= 99) // 小于等于1s
{
/* 计数清零 */
KeyTimeCount = 0;
return KEY_DOWN; // 短按状态
}
else if (KeyTimeCount >= 199) // 大于等于2s
{
/* 计数清零 */
KeyTimeCount = 0;
return KEY_DOWN_LONG; // 长按状态
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
}
/**
* 函数功能: 选取按键KEYx
* 输入参数:1 :按键1;
* 2 :按键2;
* 3 :按键3
* 返 回 值: KEYx_StateSet(KEYx_GPIO, KEYx_GPIO_PIN, KEYx_DOWN_LEVEL)
* 说 明:无。
*/
KEYState_TypeDef KEYx_Choice(int KEYIndex)
{
switch(KEYIndex)
{
case 1:
return KEYx_StateSet(KEY1_GPIO, KEY1_GPIO_PIN, KEY1_DOWN_LEVEL);
case 2:
return KEYx_StateSet(KEY2_GPIO, KEY2_GPIO_PIN, KEY2_DOWN_LEVEL);
case 3:
return KEYx_StateSet(KEY3_GPIO, KEY3_GPIO_PIN, KEY3_DOWN_LEVEL);
default:
return KEY_UP;
}
}
/**
* 函数功能: 按键KEYx控制LED
* 输入参数:无
* 返 回 值:LED1_OFF:1灯灭;
* LED2_OFF:2灯灭;
* LED3_OFF:3灯灭
* 说 明:无。
*/
void KEY_LED(void)
{
/* 读取按键状态 */
int key1State = KEYx_Choice(1);
int key2State = KEYx_Choice(2);
int key3State = KEYx_Choice(3);
/* 短按按键1 */
if (key1State == 1)
{
LED1_OFF;
}
/* 长按按键1 */
else if (key1State == 2)
{
LED3_OFF;
}
else if (key2State == 1)
{
LED2_OFF;
}
else if (key2State == 2)
{
LED3_OFF;
}
else if (key3State == 1)
{
LED3_OFF;
}
else
{
LED1_ON;
LED2_ON;
LED3_ON;
}
}
2.bsp_key.h
#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include <stm32f10x.h>
#include "bsp/delay/delay.h"
#include "bsp/led/bsp_led.h"
/* 类型定义 --------------------------------------------------------------*/
typedef enum
{
KEY_UP = 0,
KEY_DOWN = 1,
KEY_DOWN_LONG = 2,
}KEYState_TypeDef;
/* 宏定义 --------------------------------------------------------------------*/
#define KEY1 (uint8_t)0x01
#define KEY2 (uint8_t)0x02
#define KEY3 (uint8_t)0x04
#define IS_KEY_TYPEDEF(KEY) (((KEY) == KEY1) || ((KEY) == KEY2) || ((KEY) == KEY3))
/* 宏定义 --------------------------------------------------------------------*/
#define KEY1_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
#define KEY1_GPIO_PIN GPIO_Pin_7
#define KEY1_GPIO GPIOE
#define KEY1_DOWN_LEVEL 0 /* 根据原理图设计,KEY1按下时引脚为低电平,所以这里设置为0 */
#define KEY2_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
#define KEY2_GPIO_PIN GPIO_Pin_8
#define KEY2_GPIO GPIOE
#define KEY2_DOWN_LEVEL 0 /* 根据原理图设计,KEY2按下时引脚为低电平,所以这里设置为0 */
#define KEY3_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
#define KEY3_GPIO_PIN GPIO_Pin_9
#define KEY3_GPIO GPIOE
#define KEY3_DOWN_LEVEL 0 /* 根据原理图设计,KEY3按下时引脚为低电平,所以这里设置为0 */
/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void KEY_GPIO_Init(void);
KEYState_TypeDef KEYx_StateSet(GPIO_TypeDef* KEYx_GPIO, uint16_t KEYx_GPIO_PIN, uint8_t KEYx_DOWN_LEVEL);
KEYState_TypeDef KEYx_Choice(int KEYIndex);
void KEY_LED(void);
#endif // __BSP_KEY_H__
3.main.c
这边值得注意的是延时函数需要配置文件,也可以将上一篇的延时函数直接放入main.c和bsp_key.c中
STM32(一):流水灯 (标准库函数)-CSDN博客
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f10x.h"
#include "bsp/led/bsp_led.h"
#include "bsp/key/bsp_key.h"
#include "bsp/delay/delay.h"
/* 函数体 --------------------------------------------------------------------*/
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
/* 初始化 */
LED_GPIO_Init();
KEY_GPIO_Init();
while (1)
{
// /* 流水灯 */
// LED_Turn();
// Delay(100);
/* 按键控制LED */
KEY_LED();
Delay(100);
}
}
四、实验效果
按键点灯文章来源:https://www.toymoban.com/news/detail-861655.html
结束语
本文以STM32VET6为例讲解了一种按键长按和短按点灯的实现方法,当然,这只是其中一种方法,实现的方式其实还是很多。
如果还有什么问题,欢迎评论区留言,谢谢!文章来源地址https://www.toymoban.com/news/detail-861655.html
到了这里,关于STM32(二):按键 (标准库函数)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!