51单片机定时器扫描按键

定时器扫描按键

定时器每隔20毫秒扫描一次按键

问题:在之前写的按键检测函数中,要在按键按下后用Delay函数进行软件消抖,还要用while(P3_1==0)来判断是否松手,如果长期不松手,则CPU会 卡在该死循环里,不能执行其他代码,造成某些功能代码失效,这次用定时器扫描按键的方法解决该问题

key.c函数

#include <REGX52.H>
unsigned char key_keyNumber;
/**
  * @brief按键检测,之前要在按键按下后用Delay函数进行软件消抖,还要用while(P3_1==0)来判断是否松手,如果长期不松手,则CPU会	卡在该死循环里,不能执行其他代码
  * @param无
  * @retval返回被按下按键的值
  */
unsigned char Key_GetState()
{
	unsigned char keynum = 0;
	if(P3_1==0){keynum=1;}	//一有按键被按下,标志位keynum立即置位并返回,给key_loop函数处理
	if(P3_0==0){keynum=2;}
	if(P3_2==0){keynum=3;}
	if(P3_3==0){keynum=4;}
	return keynum;
}
/**
  * @brief用于返回按键标志位,main函数中调用
  * @param无
  * @retval按键标志位
  */
unsigned char key_return()
{
	unsigned char temp = 0;
	temp = key_keyNumber;
	key_keyNumber = 0;
	return temp;
}
/**
  * @brief每隔20毫秒执行一次该函数,对按键状态进行扫描
  * @param无
  * @retval无
  */
void key_loop()
{
	static unsigned char before_state,now_state;
	before_state = now_state;
	now_state = Key_GetState();		//获取按键标志位
    
    /*1.一开始没按键按下时before_state = 0,now_state = 0
      2.当按键1按下没松开时,now_state = 1,此时before_state = 0,不满足下面任何的判断
      3.20ms后该函数再次被调用,before_state = now_state = 1
      4.按键1松开,now_state = 0,此时before_state = 1,满足下面第一条if判断,key_keyNumber置1
    */
    
	//上一个状态有按键按下,现在状态没有按键按下,说明处于按下后松手阶段
    //若if(before_state == 0 && now_state == 1),则是按键按下瞬间为真,标志位置1,不用等	
	if(before_state == 1 && now_state == 0)	
	{
		key_keyNumber = 1;	//全局变量key_keyNumber置1,使用key_return函数返回给main函数使用
	}
	if(before_state == 2 && now_state == 0)	
	{
		key_keyNumber = 2;
	}
	if(before_state == 3 && now_state == 0)	
	{
		key_keyNumber = 3;
	}
	if(before_state == 4 && now_state == 0)	
	{
		key_keyNumber = 4;
	}
}

Timer0.h函数

/**
  * @brief定时器0初始化函数
  * @param无
  * @retval无
  */
void Timer0Init()		//1毫秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;
	ET0 = 1;
}

main.c函数

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
unsigned char keyNumber,key_temp;

void main()
{
	Timer0Init();	//初始化定时器
	while(1)
	{
		keyNumber = key_return();		//接收按键状态
		if(keyNumber)
		{
			key_temp = keyNumber;
		}
		NixieTube(1,key_temp);	//数码管显示按键对应数值
	}
}
/**
  * @brief中断处理函数,每隔20毫秒执行key_loop函数
  * @param无
  * @retval无
  */
void Timer0() interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x66;
	TH0 = 0xFC;
	count++;
	if(count>20)	//每隔20毫秒调用按键扫描函数
	{
		key_loop();
		count = 0;
	}
}

优化后的结果:按键按下不放时,数码管数字不会改变,当按键松开时才会变化,这期间CPU并没有卡在死循环里,可以运行其他功能

注意点:中断处理函数中的key_loop函数的实现中不能有Delay函数延时,会打乱原本的中断定时,直译的意思是每隔20毫秒延时x毫秒,显然这是不对的,此外key_loop函数的执行时间也不要大于定时器的时间,不然这一次的函数还没处理完,下一次的中断又来了

  • 22
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值