STM32入门项目——(3-4)按键控制LED代码超详解!!

一.最终实现的现象

本篇文章最终的现象就是通过按键的按下,实现LED的亮灭,比如当我第一次按下,LED亮,第二次按下,LED灭。

二.按键简介

1.按键是什么?

按键是一种常见的输入设备,按下导通,松手断开

2.按键抖动是什么?

由于案件内部使用的是机械式的弹簧片来进行通断的,所以在按下和松手的瞬间都会伴有一连串的抖动

当我们人体按下按键时是感受不到的,但是对于单片机来说,这已经无法忽视了,所以当我们要使用按键时,需要进行按键的消抖。也就是延迟一小段时间,等待弹簧片一连串的抖动消失之后,再确定按键的状态。

具体延迟多长的时间呢?可以看看下面的图片,大概延时5至10ms即可,而且在按下和松开时都需要消抖。

3.按键原理图

下接按键方式图一( 常用
下接按键方式图二( 最常用

由图一可知,按键K1一端接GND,一端接PA0口。

当按键被按下时,PA0被直接下拉到GND,此时读取PA0口的电压就是低电平

当按键未被按下时,PA0被悬空,引脚电压不确定,这是我们应该避免的。所以在这种情况下,必须要求PA0是上拉输入(此时,引脚再悬空,就是高电平)的模式,否则就会出现引脚电压不确定的错误现象。

所以有了下接图二,我们可以看到图二中外部接了一个上拉电阻。此时,当按键未被按下,引脚由于上拉作用,自然保持为高电平。按键按下,引脚为低电平。

这种情况下,引脚不会出现悬空状态,所以此时PA0口可以被配置为浮空输入或者上拉输入。如果是上拉输入,那就是内外两个上拉电阻共同作用了;这时高电平就会更强一些,对应高电平就会更加稳定。当然,当按键按下,引脚被拉到低时,损耗也就更大一些。

上接按键方式(图一)
上接按键方式(图二)

由图一可知,按键K1一端接3.3V电源,一端接PA0口。

当按键被按下时,PA0被直接上拉到3.3V,此时读取PA0口的电压就是高电平

当按键未被按下时,PA0被悬空,引脚电压不确定,这是我们应该避免的。所以在这种情况下,必须要求PA0是下拉输入(此时,引脚再悬空,就是低电平)(不过一般单片机可能并没有下拉输入的模式,所以最好用下接按键的方式)的模式,否则就会出现引脚电压不确定的错误现象。

所以有了下接图二,我们可以看到图二中外部接了一个下拉电阻。此时,当按键未被按下,引脚由于下拉作用,自然保持为低电平。按键按下,引脚为高电平。

这种情况下,引脚不会出现悬空状态,所以此时PA0口可以被配置为浮空输入或者下拉输入。具体分析和下接按键方式差不多,此处不再细讲。

那么总结一下,对于下接按键方式,也就是第一二张原理图,按键按下时引脚为低电平,松手时是高电平

对于上接按键方式,也就是第三四张原理图,按键按下时引脚为高电平,松手时是低电平

三.代码部分

1.按键代码部分

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/**
  * 函    数:按键初始化
  * 参    数:无
  * 返 回 值:无
  */
void Key_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; 

//这里我们选择开启GPIOB上的1口和11口,这里两个接口的作用就如同前面所讲的PA0口的作用一样

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
						
//将PB1和PB11引脚初始化为上拉输入
//我们使用下接模式,所以配置为上拉输入
}

/**
  * 函    数:按键获取键码
  * 参    数:无
  * 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
  * 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
  */
uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;		//定义变量,默认键码值为0
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)			

//读PB1输入寄存器(PB1口)的状态,如果为0,则代表按键1按下
	{
		Delay_ms(20);											//延时消抖

//消抖的重要性!在写代码时,一定不要忘了消抖!!

		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);	//等待按键松手

//按键按下时为低电平,也就是0,若一直按着不松手,则程序会在while循环中不断循环,直到松手变为高电平,才会退出循环
//注意,此处的while为循环语句,最后要记得加个分号

		Delay_ms(20);											//延时消抖
		KeyNum = 1;												//置键码为1
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)	
		
//读PB11输入寄存器(PB11口)的状态,如果为0,则代表按键2按下
	{
		Delay_ms(20);											//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);	//等待按键松手
		Delay_ms(20);											//延时消抖
		KeyNum = 2;												//置键码为2
	}
	
	return KeyNum;			
//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}

2.主函数部分

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"

uint8_t KeyNum;		//定义用于接收按键键码的变量

int main(void)
{
	/*模块初始化*/
	LED_Init();		//LED初始化
	Key_Init();		//按键初始化
	
	while (1)
	{
		KeyNum = Key_GetNum();		//获取按键键码
		
		if (KeyNum == 1)			//按键1按下
		{
			LED1_Turn();			//LED1翻转,也就是从亮(灭)变为灭(亮)

//LED代码在前面已发布的文章中也讲过,不太了解的可以去看看,希望有帮助
		}
		
		if (KeyNum == 2)			//按键2按下
		{
			LED2_Turn();			//LED2翻转
		}
	}
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值