stm32f407zgt6的KEY实例:长按键+短按键(查询方法,非中断)+LCD显示

1、实验目的

按键key.h
按键key.c
的理解和使用,修改

使用查询方式进行判断按键

返回按键长按的数值,和短按的数值

2、实验理论

短按和长按

按下—
判断是不是等于0
----延时去抖动
----是不是真的按下去,判断是否仍然等于0
-----是等于0,
等待按键松开,同时每5ms计算一次,判断是不是松开,同时5ms计数数值+1,
按键松开,
判断是短按还是长按,
如果长按时间大于设定的时间(根据key.h的宏定义进行修改),返回长按数值
如果小于设定时间,说明是短按,返回短按数值
在这里插入图片描述

在这里插入图片描述

3、实验代码

key.h

#ifndef __KEY_H
#define __KEY_H

#include "stm32f4xx.h"
#include "delay.h"
#include "sys.h"


#define	KEY_Press 0		//按键按下
#define	KEY_Pull	1		//按键放开

//**********************************************************
#define LongPressCount 100                     //超过100*5ms=500ms,算做长按
//****************************按键返回数值
#define KEY1Value 10    //短按
#define KEY1LongValue 11  //长按
#define KEY2Value 20
#define KEY2LongValue 22
#define KEY3Value 30
#define KEY3LongValue 33
#define KEY4Value 40
#define KEY4LongValue 44
#define KEY5Value 50
#define KEY5LongValue 55

#define NOKEY 99  //无按键
//********************************************************位操作
#define KEY1 PGin(1)	// 
#define KEY2 PGin(0)	// 
#define KEY3 PGin(4)	// 
#define KEY4 PGin(2)	// 
#define KEY5 PGin(3)	// 

/*---------------------- 按键配置宏 ------------------------*/

#define KEY1_PIN           GPIO_Pin_1       		 // KEY 引脚      
#define KEY1_PORT          GPIOG                    // KEY GPIO端口     
#define KEY1_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define KEY1_CLK_ENA()    {RCC_AHB1PeriphClockCmd( KEY1_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define KEY2_PIN           GPIO_Pin_0       		 // KEY 引脚      
#define KEY2_PORT          GPIOG                    // KEY GPIO端口     
#define KEY2_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define KEY2_CLK_ENA()    {RCC_AHB1PeriphClockCmd( KEY2_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define KEY3_PIN           GPIO_Pin_4        		 // KEY 引脚      
#define KEY3_PORT          GPIOG                    // KEY GPIO端口     
#define KEY3_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define KEY3_CLK_ENA()    {RCC_AHB1PeriphClockCmd( KEY3_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define KEY4_PIN           GPIO_Pin_2      		 // KEY 引脚      
#define KEY4_PORT          GPIOG                    // KEY GPIO端口     
#define KEY4_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define KEY4_CLK_ENA()    {RCC_AHB1PeriphClockCmd( KEY4_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define KEY5_PIN           GPIO_Pin_3// KEY 引脚      
#define KEY5_PORT          GPIOG                    // KEY GPIO端口     
#define KEY5_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define KEY5_CLK_ENA()    {RCC_AHB1PeriphClockCmd( KEY5_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

/*---------------------- 函数声明 ----------------------------*/

void 	KEY_Init(void);	//按键IO口初始化函数
u8		KEY_Scan(void);   //按键扫描

#endif //__KEY_H



key.c

/***
	***************************************************************************
	*	@file  	key.c
	*	@version V1.0.0
	*	@brief   按键接口相关函数
   ***************************************************************************
   *  @description
	*
	*  初始化按键引脚,配置为上拉输入、速度等级50M。
	* 	
	***************************************************************************
***/

#include "key.h"  
#include "Lcd_Driver.h"  
// 函数:按键IO口初始化
//
void KEY_Init(void)
{
    
    		
	GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
	
	KEY1_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	//上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = KEY1_PIN;	 
	GPIO_Init(KEY1_PORT, &GPIO_InitStructure);	
	
	KEY2_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输输入模模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	//上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = KEY2_PIN;	 
	GPIO_Init(KEY2_PORT, &GPIO_InitStructure);	

	
	KEY3_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	//上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = KEY3_PIN;	 
	GPIO_Init(KEY3_PORT, &GPIO_InitStructure);	

	KEY4_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输输入模模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	//上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = KEY4_PIN;	 
	GPIO_Init(KEY4_PORT, &GPIO_InitStructure);	


	KEY5_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输输入模模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	//上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = KEY5_PIN;	 
	GPIO_Init(KEY5_PORT, &GPIO_InitStructure);	

  KEY1=1;KEY2=1;KEY3=1;KEY4=1;KEY5=1;
	
}

// 函数:按键扫描
//	返回:KEY_ON - 按键按下,KEY_OFF - 按键放开 
//			
u8	KEY_Scan(void)
{
    
    
	u8 CountPressTime=0;//长按时间计数
	//**************************************************第一个按键判断
	if(KEY1 == 0 )	//检测按键是否被按下if( GPIO_ReadInputDataBit ( KEY1_PORT,KEY1_PIN) == 0 )
	{
    
    	
		Delay_ms(10);	//延时消抖	
		if(KEY1== 0)	//再次检测是否为低电平
		{
    
    
			while(KEY1==0)
			{
    
    			
				Delay_ms(5);	
				CountPressTime++;		 				
			};	//等待按键放开
			//判断是不是长按下	
			if(CountPressTime>LongPressCount)
			{
    
    
				CountPressTime=0;
				return KEY1LongValue;	//返回按键长按的按下标志
			}
			//如果是短按,返回短按的数值
			else 
				return KEY1Value;	//返回按键按下标志
		}
	}
		
		//**************************************************第2个按键判断
	else if(KEY2== 0 )	//检测按键是否被按下
	{
    
    	
		Delay_ms(10);	//延时消抖
		if(KEY2== KEY_Press)	//再次检测是否为低电平
		{
    
    
			while(KEY2==0)
			{
    
    
				
				Delay_ms(5);	
				CountPressTime++;
			};	//等待按键放开
			//判断是不是长按下
			if(CountPressTime>LongPressCount)
			{
    
    
				CountPressTime=0;
				return KEY2LongValue;	//返回按键长按的按下标志
			}
			//如果是短按,返回短按的数值
			else 
				return KEY2Value;	//返回按键按下标志
		}
	}
		
		
	//**************************************************第3个按键判断
	else if(KEY3== 0 )	//检测按键是否被按下
	{
    
    	
		Delay_ms(10);	//延时消抖
		if(KEY3== KEY_Press)	//再次检测是否为低电平
		{
    
    
			while(KEY3==0)
			{
    
    
				
				Delay_ms(5);	
				CountPressTime++;
				
			};	//等待按键放开
			//判断是不是长按下
			if(CountPressTime>LongPressCount)
			{
    
    
				CountPressTime=0;
				return KEY3LongValue;	//返回按键长按的按下标志
			}
			//如果是短按,返回短按的数值
			else 
				return KEY3Value;	//返回按键按下标志
		}
	}
		
	//**************************************************第4个按键判断
	else if(KEY4== 0 )	//检测按键是否被按下
	{
    
    	
		Delay_ms(10);	//延时消抖
		if(KEY4== KEY_Press)	//再次检测是否为低电平
		{
    
    
			while(KEY4==0)
			{
    
    
				
				Delay_ms(5);	
				CountPressTime++;
				
			};	//等待按键放开
			//判断是不是长按下
			if(CountPressTime>LongPressCount)
			{
    
    
				CountPressTime=0;
				return KEY4LongValue;	//返回按键长按的按下标志
			}
			//如果是短按,返回短按的数值
			else 
				return KEY4Value;	//返回按键按下标志
		}
	}
		
	//**************************************************第5个按键判断
	else if(KEY5== 0 )	//检测按键是否被按下
	{
    
    	
		Delay_ms(10);	//延时消抖
		if(KEY5== KEY_Press)	//再次检测是否为低电平
		{
    
    
			while(KEY5==0)
			{
    
    
				
				Delay_ms(5);	
				CountPressTime++;
				
			};	//等待按键放开
			//判断是不是长按下
			if(CountPressTime>LongPressCount)
			{
    
    
				CountPressTime=0;
				return KEY5LongValue;	//返回按键长按的按下标志
			}
			//如果是短按,返回短按的数值
			else 
				return KEY5Value;	//返回按键按下标志
		}
				
	}

	else 
		return NOKEY;		
	
}



main.c

#include "stm32f4xx.h"
#include "led.h"   
#include "delay.h"
#include "key.h"
#include "usart.h"  
#include "sys.h"  

#include "Lcd_Driver.h"  
//第一个,修改头文件led.h,配置硬件的IO对应
//修改led.c文件
int main(void)
{
    
    
	//u8 key_flag = 0;	//按键标志
	u8 keyvalue=0;
	
  int aaa=123;
	float  wendu=50.63;
	
	Delay_Init();		//延时函数初始化
  KEY_Init();
  Lcd_Init();
	Delay_ms(20);
	Lcd_Clear(YELLOW); 
//	LCD_ShowStringAsc32(0,0,RED,WHITE,"475");
//	LCD_ShowStringAsc32(0,32,RED,WHITE,"lmf666");//第一个是行,16为倍数,列以32为倍数,字体颜色,画布颜色,显示的字符串

		//显示字符
		LCD_ShowCharAsc32(0,0,RED,WHITE,'c');
		LCD_ShowCharAsc32(16,0,RED,WHITE,'d');
		LCD_ShowCharAsc32(16*2,32,RED,WHITE,'9');
	//显示字符串	
		LCD_ShowStringAsc32(0,64,RED,WHITE,"475");
		LCD_ShowStringAsc32(0,64+32,RED,WHITE,"hello,lmf.217");
  //显示整数  
		LCD_ShowNumAsc32(0,32*4,RED,WHITE,aaa,3);
	//显示浮点数	
		LCD_ShowFloatAsc32(0,32*5,RED,YELLOW,wendu,2);//浮点数
		
		LCD_ShowStringAsc32(0,32*6,RED,WHITE,"KEY=");
	
	while (1)
	{
    
    			
		

		//扫描按键
		keyvalue=KEY_Scan();
    switch(keyvalue)
		{
    
    
			//第一个按键短按、长按
			case KEY1Value:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY1Value,3);
					break;
			
			case KEY1LongValue:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY1LongValue,3);
					break;
			
				//第2个按键短按、长按
			case KEY2Value:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY2Value,3);
					break;
			
			case KEY2LongValue:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY2LongValue,3);
					break;
			
				//第3个按键短按、长按
				case KEY3Value:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY3Value,3);
					break;
				
			  case KEY3LongValue:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY3LongValue,3);
					break;
				
				//第4个按键短按、长按
				case KEY4Value:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY4Value,3);
					break;
			  case KEY4LongValue:
					LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY4LongValue,3);
					break;
				
				//第5个按键短按、长按
				case KEY5Value:
						LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY5Value,3);
						break;
				case KEY5LongValue:
				    LCD_ShowNumAsc32(16*5,32*6,RED,WHITE,KEY5LongValue,3);
		        break;
			
			default:break;
					
		}		
    keyvalue=NOKEY;		//把按键数值清空,给下次使用
		
	
  }
}

delay.h

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f4xx.h"

void Delay_Init(void);				//延时函数初始化
void Delay_ms(u32 nTime);	//毫秒延时函数

#endif //__DELAY_H


delay.c

/***
	***************************************************************************
	*	@file  	delay.c
	*	@brief   delay接口相关函数
   ***************************************************************************
   *  @description
	*
	*  SysTick定时器配置为1ms中断,实现毫秒延时
	* 	
	***************************************************************************
***/

#include "delay.h"

static u32 TimingDelay;  //计数变量


//	函数:延时初始化
//	说明:配置 SysTick 为1ms中断,并启动定时器
//
void Delay_Init(void)
{
    
    
	SysTick_Config(SystemCoreClock / 1000);  //配置SysTick时钟为1ms中断
}

//	函数:计时函数
//	说明:在 SysTick 中断服务函数里被调用
//
void TimingDelay_Decrement(void)
{
    
    
	if (TimingDelay != 0)
	{
    
     
		TimingDelay--;
	}
}

//	函数:毫秒延时
// 参数:nTime - 延时时间,单位ms
//	说明:每次调用都会重新给TimingDelay赋值,实现 n 毫秒的延时,最大延时 4294967295 ms。	
//
void Delay_ms(u32 nTime)
{
    
     
	TimingDelay = nTime;

	while(TimingDelay != 0);
}





sys.h

#ifndef __SYS_H
#define __SYS_H	 
#include "stm32f4xx.h" 

//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入


#endif

4、实验效果

按下不同的按键,显示不同的按键数值KEY=xx,
XX=10,11,20,21,30,31,40,41,50,51,99按键数值。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lmf666/article/details/111935412