一段基于定时器用作按键消抖的代码

 以前我使用按键消抖都是用的延时函数,延时个10-20ms,用软延时的方式比较简单,但是会极大浪费单片机的资源,并且延时的并不是很精确,所以使用定时器来代替软延时。

#include <reg51.h>
#define NoKeyProcess 0
#define Key1_Press 	 1
#define Key2_Press 	 2
#define Key3_Press 	 3
#define Key4_Press 	 4

void Key()
{
    sbit key1 = P3^1;	 //1号病床输入
    sbit key2 = P3^0;	 //2号病床输入
    sbit key3 = P3^2;	 //3号病床输入
    sbit key4 = P3^3;	 //4号病床输入
    static unsigned char Key_status = 0,priv_key_val = 0;
    unsigned char Key_Value = 0;
     
    Key_Value|=(key1==1)? NoKeyProcess:Key1_Press;                //如果按键按下了(括号内值为假),Key_Value = 1.
    Key_Value|=(key2==1)? NoKeyProcess:Key2_Press;                //如果按键按下了(括号内值为假),Key_Value = 2.
    Key_Value|=(key3==1)? NoKeyProcess:Key3_Press;                //如果按键按下了(括号内值为假),Key_Value = 3.
    Key_Value|=(key4==1)? NoKeyProcess:Key4_Press;                //如果按键按下了(括号内值为假),Key_Value = 4.
    
    switch(Key_status)
	{
		case 0: //Key pressed
			if(Key_Value)
			{
				priv_key_val=Key_Value;
				Key_status++;
			}
		break;
		case 1: //Confirm key pressed
			if(priv_key_val==Key_Value)
			{
				Key_status++;		
			}
			else
				Key_status=0;
			break;
		case 2:// Wait to release
			if(Key_Value !=priv_key_val)
			{
				Key_status = 0;
				Key_Process(priv_key_val); //按键处理函数				
			}
				break;
		default:break;
	}
}

void Timer0_ISR() interrupt 1 //TIM0 中断服务函数
{
		TH0=T0RH;
		TL0=T0RL;
		vKey_Scan();
}

注释:如果病床1号按下按键,Key_Value的值就为 1,然后进入switch的case0,因为Key_Value的值为真,所以进入if把值赋给priv_key_val,然后等下次进入switch,也就是10ms后再次进入Key函数,此时1号病床的按键还是按下的,因为人体按按键最快的时间大概是100ms之后,所以第二次来到case1,这里是确认了按键确实按下了,而不是因为抖动,并且还判断这次按下的键是不是还是按键1,如果是,就等下个10ms进入case2,如果不是同一个按键按下了就退回到case0,case2是检测按键是否释放,如果是,就将Key_status = 0方便下次按键判断然后执行那件处理函数。。。

当没有按键按下时,Key_Value值就为0,就进不去case1了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用定时器作为计数器并使用数码管显示的示例代码代码中使用了定时器0和定时器1,其中定时器0用作计数器,定时器1用于控制数码管的显示。按键控制计数暂停的功能可以通过外部中断实现,此处未进行代码实现。 ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int // 数码管显示表 uchar code seg_table[10] = { 0x3F, // 0 0x06, // 1 0x5B, // 2 0x4F, // 3 0x66, // 4 0x6D, // 5 0x7D, // 6 0x07, // 7 0x7F, // 8 0x6F // 9 }; // 计数器值 volatile uint count = 0; // 数码管位选控制变量 volatile uchar seg_ctrl = 0; // 定时器0中断处理函数 void timer0_isr() interrupt 1 { TH0 = 0xFC; // 重置定时器0计数值 TL0 = 0x67; count++; // 计数器加1 } // 定时器1中断处理函数 void timer1_isr() interrupt 3 { // 数码管位选控制变量加1 seg_ctrl++; if (seg_ctrl >= 4) { seg_ctrl = 0; } // 根据位选控制变量选择要显示的位 switch (seg_ctrl) { case 0: P2 = 0xFE; // 第一位数码管位选 P0 = seg_table[count % 10]; // 显示个位数 break; case 1: P2 = 0xFD; // 第二位数码管位选 P0 = seg_table[count / 10 % 10]; // 显示十位数 break; case 2: P2 = 0xFB; // 第三位数码管位选 P0 = seg_table[count / 100 % 10]; // 显示百位数 break; case 3: P2 = 0xF7; // 第四位数码管位选 P0 = seg_table[count / 1000 % 10]; // 显示千位数 break; } } void main() { TMOD = 0x11; // 定时器0工作方式1,定时器1工作方式1 TH0 = 0xFC; // 初始化定时器0计数值 TL0 = 0x67; TH1 = 0xFD; // 初始化定时器1计数值 TL1 = 0xFD; ET0 = 1; // 开启定时器0中断 ET1 = 1; // 开启定时器1中断 EA = 1; // 开启总中断 TR0 = 1; // 启动定时器0 TR1 = 1; // 启动定时器1 while (1); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值