蓝桥杯嵌入式(三)按键配置

蓝桥杯嵌入式比赛所使用的是CT117E嵌入式竞赛板,板子上共有4个独立按键和一个复位按键,在进行按键配置前,我们需要先查看板子的原理图,知道这四个按键所连接的引脚。

由原理图可知,B1、B2、B3、B4四个按键分别对应PA0、PA8、PB1、PB2四个引脚。四个按键都连接了上拉电阻,所以都是低电平有效

了解了按键的连接,接下来我们就可以对按键进行配置了,配置代码如下:

void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB , ENABLE);
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;			//上拉输入
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

这段代码就是用来初始化按键输入的IO口的,实现PA0、PA8、PB1、PB2的输入设置。

按键的配置步骤和LED的步骤相同

第一步:不管使用任何外设,永远都是先使能相应的时钟,通过函数RCC_APB2PeriphClockCmd()来使能APB2总线上的GPIOA、GPIOB的时钟。

第二步就是对引脚的具体配置,按键输入,我们把引脚配置为上拉输入

接下来我们看看头文件里面的代码。

#ifndef _KEY_H
	#define _KEY_H
	#include "stm32f10x.h"
	//key
	void Key_Init(void);
	
	#define		KEY1	GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
	#define		KEY2	GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
	#define		KEY3	GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
	#define		KEY4	GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)

#endif

这段代码里面最关键就是四个宏定义:

扫描二维码关注公众号,回复: 9130655 查看本文章

采用库函数GPIO_ReadInputDataBit读取IO口的值,它的返回值就是所读取IO口的电平状态,高电平返回1,低电平返回0。

配置完毕,我们还需要知道哪个按键被按下,所以接下来就要写按键读取函数,之前我一直都使用原子点的方法来处理按键,进入蓝桥杯备赛后,查阅了很多资料,偶然发现了一种简单实用的方法,代码如下:

//key
void Key_Read(void)
{
	static u16 key1_sum=0,key2_sum=0,key3_sum=0,key4_sum=0;
	//key1
	if(KEY1==0)
	{
		key1_sum++;
		if(key1_sum==1)			//短按		
		{
			//需要实现的功能	
		}
		
		if(key1_sum==20)		//长按
		{
			//需要实现的功能
			key1_sum=10;
		}
	}
	else 
		key1_sum=0;
}

4个按键的代码相同,可以直接复制粘贴。

代码第4行定义了4个静态变量,这是用来计数的,其实就是区分长短按,根据长按触发时间的长短,可以调整变量类型的大小。

按键为低电平有效,当读取到按键按下时,key1_sum就自加1。

如果是短按,按键会及时弹起,就只会进入短按程序执行(第9行),按键弹起后key1_sum就会清零。

如果是长按key1_sum就会根据按键扫描的时间不断加1,直到松开按键,计数值才会清零。第17行给key1_sum赋值,是为了不断的触发长按。

长按计数值=长按触发时间 / 按键扫描时间

写完按键读取函数,接下来就要不断的扫描这个函数,就需要使用到嘀嗒定时器中断。中断中不宜放置太多代码,所以我们使用标志位来实现按键扫描。首先在main.c中定义一个标志位Key_Flag,中断中的代码如下:

extern u8 Key_Flag;			//按键扫描标志
void SysTick_Handler(void)
{
	static u16 ms1=0;
	TimingDelay--;
	
	if(++ms1==50)			//50ms
	{
		ms1=0;
		Key_Flag=1;
	}
}

主函数代码:

//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);
	Led_Init();
	Key_Init();
	while(1)
	{
		if(Key_Flag)        //按键扫描
		{
			Key_Flag=0;    //标志位清零
			Key_Read();
		}
	}
}

这个中断可看做1ms定时器,使用静态变量ms1来计数,计数值为50,按键扫描时间就为50ms。每50ms就把计数器清零,按键标志位置1,在主函数中,就会执行按键读取函数(也就是每50ms执行一次)。按键扫描时间定为50ms是为了让按键充分消抖

到此,按键的配置就写完了,我们写个简单的小程序来试试。

#include "stm32f10x.h"
#include "io.h"

u32 TimingDelay = 0;

u8 Key_Flag=0;			//按键扫描标志
extern u16 LED;
//key
void Key_Read(void)
{
	static u16 key1_sum=0,key2_sum=0,key3_sum=0,key4_sum=0;
	//key1
	if(KEY1==0)
	{
		key1_sum++;
		if(key1_sum==1)			//短按		
		{
			LED ^= (1<<8);		
			Led_Set();
		}
		
		if(key1_sum==20)		//长按
		{
			LED ^= (1<<9);
			Led_Set();
			key1_sum=10;
		}
	}
	else 
		key1_sum=0;
}

//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);
	Led_Init();
	Key_Init();
	while(1)
	{
		if(Key_Flag)	//按键扫描
		{
			Key_Flag=0;
			Key_Read();
		}
	}
}

这个程序中,短按B1实现LED1的翻转;长按B1(长按触发时间为1s)就会让LED2不停地闪烁,26行key1_sum=10,只要只是按着B1不松开,LED2就每隔500ms翻转一次。

发布了4 篇原创文章 · 获赞 0 · 访问量 211

猜你喜欢

转载自blog.csdn.net/Cola_Y/article/details/104278341