51单片机一个按键,通过单击,双击,三击,长按实现四种不同的led特效并且每次切换模式伴随不同的音效。(连击4下为无效指令)

一个定时器负责扫描按键按下的时间长短,一个定时器负责实现具体的led特效功能,主函数循环扫描按键,避免了占用cpu资源过多,导致程序堵塞,无法扫描到按键等问题;还可以通过定时器来扫描按键按下,时长等,想要实现的程序放在主函数中执行。新人第一次写博客,不足之处欢迎指正,感谢!

主函数部分:

#include <REGX52.H>
#include "DELAY.h"
#include "INTRINS.h"
#include "BEEP.h"
#define LED P2 
sbit KEY = P3^0;
unsigned char D1 = 0xFE;
unsigned char D2 = 0xFD;
unsigned char D3 = 0xFB;
unsigned char D4 = 0xF7;
unsigned char num,compare;
unsigned char Flag1,Flag2;
unsigned int counter,time,a,b,c,d;


/**************************************
通过定时器来实现一个按键,单击闪烁灯,双击跑马灯,三击呼吸灯,长按流星灯
并且每次切换模式伴随不同的音效。(连击4下为无效指令)
***************************************/


void TimerInit(void)		//@11.0592MHz
{
	TMOD=0x11;
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
	TL1 = 0xA4;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF0 = 0;	
	TF1 = 0;
	TR0 = 0;	
	TR1 = 0;
	EA = 1;
	ET1 = 1;
	ET0 = 1;
	PT0 = 1;
}
void key_count()
{
		if(KEY==0)		//按键按下	
		{	
			Delayms(5) ; 			//消抖
//			TR1 = 0;		//可选择按键按下时停止任何功能
			if(KEY==0)   
			{	
				TR0 = 1 ;  //开始计时
				while(KEY==0);
				TR0 = 0 ; //结束计时
			}
		}
		if(KEY==1)		//松手检测
		{
			if(counter>=100)  //按下超过时间
			{
				TR1 = 0;  //防止呼吸灯模式之间切换造成的影响
				Beep_voice(6);
				LED = 0xFF;  //重置LED状态
				Flag1 = 4; 
				TR1 = 1;
			}
			else if((counter>1)&&(counter<100)) //每次按下不超过1秒
			{
				num ++; 			//按键次数加1
				time = 7000;	//如果此时按键再次按下会被重新赋予6000
			}
				counter = 0;  //按下检测时间清0
		
		if(time) 	//大于0,减少
		{
				time--; //通过自减来计时
			if(time==0) //计时结束,开始判断
			{
				LED = 0xFF;
				switch(num)  //判断按下几次
				{
					case 1:     //单击开启定时器模式一
					{
						TR1 = 0;
						Beep_voice(1);
						LED = 0xFF;
						Flag1 = 1;
						TR1 = 1;
						break ;
					}
					case 2:   //双击开启定时器模式二
					{
						TR1 = 0;
						Beep_voice(3);
						LED = 0xFF;
						Flag1 = 2;
						TR1 = 1;
						break ;
					}
					case 3:		//三击开启定时器模式三
					{
						TR1 = 0;
						Beep_voice(4);
						LED = 0xFF;
						Flag2 = 0;
						Flag1 = 3;
						TR1 = 1;
						break ;
					}										
				}
				time=0;
				num=0;			//按键按下次数清0					
			}
		}
	}
}
void main()		//实现一个按键按下:单击闪烁灯,双击跑马灯,三级呼吸灯,长按流星灯
{
	TimerInit();
	LED = 0xFF;
	while(1)
	{
	 key_count();
	}	
}

void Time0() interrupt 1  //定时器10ms进入一次中断扫描,计数值加1
{
	counter ++;
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
}

void Time1() interrupt 3
{
	TR1=0;	
 if(Flag1==4) 		//流星灯
{
	static unsigned int count,d;
	count ++ ;
	d++ ;
	if(count>=1600)
	{	
		D1 = _crol_(D1,1);
		D2 = _crol_(D2,1);		
		D3 = _crol_(D3,1);
		D4 = _crol_(D4,1);	
		count = 0;
	}
	d%=100;
	if(d<=5)LED &= D1;
	else LED |= ~D1;
	if(d<=10)LED &= D2;
	else LED |= ~D2;
	if(d<=40)LED &= D3;
	else LED |= ~D3;
	if(d<=100)LED &= D4;
	else LED |= ~D4;
	
	TL1 = 0xA4;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
 }
	if(Flag1==3)  	//呼吸灯
{
	 d++;
     c ++ ;
     c %= 100 ;//到达100后清0
	if(d==50)
	{
		compare ++;
		d=0;
		if(compare==100){Flag2=~Flag2;compare=0;}
	}
	if(Flag2!=0xFF)
	{	
		if(c>compare)
		{
			P2_0 = 1;
		}
		else
		{
			P2_0 = 0;
		}
	}
	if(Flag2==0xFF)
	{
		if(c>compare)
		{
			P2_0 = 0;
		}
		else
		{
			P2_0 = 1;
		}		
	}
	 TL1 = 0xA4 ;    //100us
     TH1 = 0xFF ;
}
	if(Flag1==2)		//跑马灯
	{
		b++;
		if(b==200)
		{
			LED = D1;
			D1 = _crol_(D1,1);
			b=0;
		}
			TL1 = 0x66;		//设置定时初值1ms
			TH1 = 0xFC;		//设置定时初值
	}
	if(Flag1==1)			//闪烁灯
	{
		a++;
		if(a==300)
		{
			a=0;
			LED = ~LED;
		}
		TL1 = 0x66;		//设置定时初值1ms
		TH1 = 0xFC;		//设置定时初值	
	}
	TR1=1;
}



蜂鸣器部分:


#include <REGX52.H>
#include "DELAY.h"
sbit Beep = P2^5;

void Beep_voice(unsigned int e)
{
	unsigned int j ;
	for(j=0;j<400;j++)
	{
		Beep = ~Beep ;
		Delayus(e);
	}
}


延时函数部分:

#include<intrins.h>
void Delayus(unsigned int xus)		//@11.0592MHz
{
	unsigned char i;
	while(xus--)
	{
	_nop_();
	i = 25;
	while (--i);
	}
}

void Delayms(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

  • 7
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
下面是一个基于51单片机的独立按键双击按的驱动代码,供参考: ``` #include <reg51.h> #define KEY P3_3 // 定义按键连接的引脚 sbit LED = P1_0; // 定义 LED 连接的引脚 unsigned char key_buf = 0; // 按键缓存 unsigned char key_count = 0; // 按键计数器 unsigned char key_flag = 0; // 按键标志位 void delay_ms(unsigned int n); // 延时函数 void main() { KEY = 1; // 设置按键为输入模式 while(1) { if(KEY == 0) // 检测按键是否按下 { delay_ms(10); // 延时去抖动 if(KEY == 0) // 再次检测按键是否按下 { key_buf++; // 储存按键按下的次数 key_flag = 1; // 标记按键按下 } while(!KEY); // 等待按键释放 } if(key_flag) // 如果按键被按下 { delay_ms(10); // 延时去抖动 if(KEY == 0) // 如果按键没有释放 { key_count++; // 计数器加 1 if(key_count >= 100) // 如果按下超过 1 秒 { LED = 1; // 点亮 LED } } else // 如果按键释放了 { if(key_buf == 1) // 如果只按了一次 { LED = !LED; // 点亮 LED } else if(key_buf == 2) // 如果按了两次 { LED = 0; // 熄灭 LED } key_buf = 0; // 清空按键缓存 key_count = 0; // 清空计数器 key_flag = 0; // 清除按键标志位 } } } } void delay_ms(unsigned int n) { unsigned int i, j; for(i = 0; i < n; i++) { for(j = 0; j < 125; j++); } } ``` 该代码实现了以下功能: - 检测独立按键的按下和释放; - 记录按键的按下次数; - 判断按键单击还是双击; - 判断按键是否按; - 在 LED 上进行相应操作。 需要注意的是,该代码中的延时函数可能需要根据实际情况进行调整。同时,该代码只能处理一个按键,如果需要处理多个按键,需要进行相应的修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式嘉人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值