3.1  按键原理分析

首先我们可以看到按键连接在GND一端,然后通过按键连接在另外一端的是单片机的引脚,此时我们注意到单片机的引脚分别是P30,P31,P32 从原理图上面可以简单看出来单片机的引脚并没有接上拉电阻,因为在STC89C52单片机中他的P3引脚具有内部上拉,这样就可以不用接上拉电阻了,如果接的话也是可以的,一般可以接上10K的上拉电阻。其中P30,P31可以作为普通的按键去使用,这里需要注意的是,因为在单片机中这两个引脚是单片机串口脚位,P32是单片机的外部中断,所以接下面我们可以撰写程序去让大家理解的更加深刻。

3.2  按键的触发过程

按键触发我们一般分为三个步骤

1.按下瞬间

2.按下不动

3.松开瞬间

/**********************************
函数名: Chiclet_Keyboard_Scan
传递参数: 无
返回参数: 无
函数作用: 按键函数
**********************************/
void Chiclet_Keyboard_Scan(void)
{
  if(K1 == 0)//按键K1为低电平
  {
    usleep(2);//2ms消抖
    if(K1 == 0)//按键K1依然为低电平,此时确认是K1按下
    {
    //这里是按下瞬间的程序撰写的地方
    LED=0;
    }
    while(!K1)//while死循环,直到抬手跳出
    {
      //这里是长按的程序撰写的位置
      LED=0;
      usleep(500);//2ms消抖
      LED=1;
      usleep(500);//2ms消抖
    }												
    //这里是抬手跳出的程序撰写位置
    LED=1;
  }
}

从上述程序位置可以看到按键的三个步骤分别写在不同的位置,我们简单分析一下,第一个 if 是判断是否按下按键,然后第二个 if 是确认就是人为按下按键中间的延时是软件的消抖,这样可以为了防止因为电压电流等问题出现异常出现按键误触。

3.4  按键触发外部中断

/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
  IT0 = 1;		//设置外部中断为下降沿触发
  EX0 = 1;		//打开外部中断开关
  EA = 1;			//打开总中断开关
  while(1) 
  {
    Chiclet_Keyboard_Scan();
  }
}
/**********************************
函数名: exint0
中断号: 0
函数作用: 外部中断0 
**********************************/
void exint0() interrupt 0
{
   LED = ~LED;
   usleep(500);
}

通过对数据手册的分析,外部中断可以有两个触发方式,第一则是下降沿触发,第二就是低电平触发

通过上面程序可以看出触发方式的不同可以应用在不一样的地方,但是一般情况下我们都是在按下按键出进行处理。下面通过具体的示例展开对实用按键函数的说明

3.4 几种实用的按键函数

看到这里我们因为程序在写在单独的.c .h文件中,所以需要了解他们之间的关系以及分别代表着什么,详细可以观看下面的文章。

第三章 按键
.h .c 文件在keil 5中如何跳转的详细讲解

.h .c 文件的具体意义 头文件(.h): 头文件包含函数、变量和数据结构的声明。它们通常包含函数原型、宏...

推荐 2023-08-29

第一种

key.c

/**********************************
包含头文件
**********************************/
#include "key.h"
/**********************************
变量定义
**********************************/
uchar key_Flag = 0;		//独立按键标志位

/**********************************
函数名: Chiclet_Keyboard_Scan
传递参数: 无
返回参数: 键值
函数作用: 按键函数
**********************************/
uchar Chiclet_Keyboard_Scan(void)
{
	if(K1==1 && K2==1 && K3==1) key_Flag = 1;
	
	if(K1==0 && key_Flag==1)	//K1是否按下
	{	
		usleep(2);						  //消抖
		if(K1==0 && key_Flag==1)//再次判断K1是否按下
		{
			key_Flag = 0;
			return 1;							//返回1
		}
	}
	
	if(K2==0 && key_Flag==1)
	{
		usleep(2);
		if(K2==0 && key_Flag==1)
		{
			key_Flag = 0;
			return 2;
		}
	}
	
	if(K3==0 && key_Flag==1)
	{
		usleep(2);
		if(K3==0 && key_Flag==1)
		{
			key_Flag = 0;
			return 3;
		}
	}
	
	return 0;//没有按键按下,返回0
}


key.h

#ifndef _KEY_H_
#define _KEY_H_
/**********************************
包含头文件
**********************************/
#include "main.h"
/**********************************
PIN口定义
**********************************/
sbit K1=P3^0;			//独立按键K1引脚 P2.2
sbit K2=P3^1;			//独立按键K2引脚 P2.3
sbit K3=P3^2;			//独立按键K3引脚 P2.4

/**********************************
函数声明
**********************************/
uchar Chiclet_Keyboard_Scan(void);		//独立按键扫描函数
#endif

第二种

key.c

/**********************************
包含头文件
**********************************/
#include "key.h"
/**********************************
变量定义
**********************************/
uchar key_Flag = 0;		//独立按键标志位

/**********************************
函数名: Chiclet_Keyboard_Scan
传递参数: 无
返回参数: 键值
函数作用: 按键函数
**********************************/
uchar Chiclet_Keyboard_Scan(void)
{
	if(K1 == 0)//按键K1为低电平
	{
		usleep(2);//2ms消抖
		if(K1 == 0)//按键K1依然为低电平,此时确认是K1按下
		{
			//这里是按下瞬间的程序撰写的地方
      key_Flag=1;
		}
		while(!K1);//while死循环,直到抬手跳出											
		//这里是抬手跳出的程序撰写位置
    return key_Flag;
	}
  
  if(K2 == 0)//按键K1为低电平
	{
		usleep(2);//2ms消抖
		if(K2 == 0)//按键K1依然为低电平,此时确认是K1按下
		{
			//这里是按下瞬间的程序撰写的地方
      key_Flag=2;
		}
		while(!K2);//while死循环,直到抬手跳出											
		//这里是抬手跳出的程序撰写位置
    return key_Flag;
	}
  
  if(K3 == 0)//按键K1为低电平
	{
		usleep(2);//2ms消抖
		if(K3 == 0)//按键K1依然为低电平,此时确认是K1按下
		{
			//这里是按下瞬间的程序撰写的地方
      key_Flag=3;
		}
		while(!K3);//while死循环,直到抬手跳出											
		//这里是抬手跳出的程序撰写位置
    return key_Flag;
	}
	
	return 0;//没有按键按下,返回0
}

key.h  不变

按键函数是相对十分实用的一个驱动,等后期我们学习定时器之后可以根据定时器,去写一些长按,短按,等的按键方式,这样可以更加完善人机交互系统。

 

发表回复

后才能评论