基于51单片机按键连加连减的检测

题目要求

按键计数:

1. 用普通按键、数码管实现对于按键的计数 (范围 0 - 100
2.数码管在全程不可存在肉眼可见的熄灭
3.对按键连续快按,系统能正常计数
4.两个按键(按键 1 与按键 2 )分别实现加与减
5.加到 100 再加后变为 0 重新加,减到 0 后再减也是 0
6.对按键 1 长按,系统能保持固定频率加一
7.对按键 2 长按,系统只会减一,除非下一次按下
8.计数掉电保存

题目的解读

题目可以分为两个部分

单机的加减与长按的连加连减

我们先讨论单机的加减再讨论讨论如何实现按键的连加与连减的

单机加减的实现

单机加减中有一个需要注意的地方就是

总体思路为定义一个变量count

当按键加按下时,count++,按键减按下时count-- ; 

达到100时取余,为零时判断 

连击加减的实现

代码部分

主函数

#include <REGX52.H>
#include "Key.h"
#include "Show.h"
#include "I2C.h"
#include "AT24C02.h"
#include "Timer0.h"
#include "Delay.h"
#include "Nixie.h"

unsigned char Number,count;
unsigned char ge,shi,bai,i,j;
extern unsigned char Long_Press,Minor_Press;//外部变量不可赋值只能在定义处赋值

void main()
{   Timer0_Init();
	count=18;          //计数值
	while(1)
	{
		ShowNum(count);//刷新处
		Number=Key();
		if(Number==1)
		{
		  there:      //防止出现加到100不能减的情况
		  count++;
		  ShowNum(count);
		  if(count==101)//101即为0
		  {
			  count=0;
			  Number = Key();
			  if(Number==1)
			  { 
				  count=0;
			  }
			  else goto here;
		  }
		}
		if(Number==2)
		{
		  here:
		  count--;
		  ShowNum(count);
		  if(count==-1)
		  {   
			  Number=Key();
			  if(Number==2)
			  {
				  count=0;
			  }
			  else goto there;
		  }
		}
		if(Number==3)
		{
			AT24C02_WriteByte(1,count);//写入数据局与读出数据
			Delay(5);
		}
		if(Number==4)
		{
			count=AT24C02_ReadByte(1);
		}
		if(count>=101){	count=0;}    //连加并未有按键持续按下
		if(count<=-1){count=100;}    //因此在这里再加判断来解决
	}
}

void Timer0_Routine(void) interrupt 1  //中断程序代码1ms
{
	static unsigned int T0Count1=0,T0Count2=0,T0Count3=0,T0Count4=0;
    //静态占据空间,要注意的是静态变量定义前不能有语句的存在
    
	TL0=0x66;//1ms
	TH0=0xFC;
	T0Count1++;
	if(T0Count1>=20)//20ms
	{   
		T0Count1=0;
		Key_Loop();//每隔20毫秒调用一次
	}
	T0Count2++;
	if(T0Count2>=2)//2ms
	{   
		T0Count2=0;
		Nixie_Loop();
	}
	if(Long_Press)
	{   
		T0Count3++;
		if(T0Count3>=100)
		{   
			T0Count3=0;//加加进行
			count++;
		}
    }
	if(Minor_Press>=2)
	{
		T0Count4++;
		if(T0Count4>=100)
		{   
			T0Count4=0;
			count--;//减减进行
		}
	}
}

按键检测部分

#include <REGX52.H>
#include "Delay.h"

unsigned char Key_KeyNumber,Long_Press=0,Minor_Press=0,Countint1,Countint2;
unsigned char First,Second;

unsigned char Key(void)       //返回Key Number的值
{   unsigned char Temp=0;     //先清零按键值再返回按键的值
	Temp=Key_KeyNumber;       //中间变量为按键值
    Key_KeyNumber=0;          //否则会一直返回上一次的值
	return Temp; 
}
unsigned char Key_GetState()
{   unsigned char KeyNumber=0;
	if(P3_1==0){KeyNumber=1;}
	if(P3_0==0){KeyNumber=2;}
	if(P3_2==0){KeyNumber=3;}
	if(P3_3==0){KeyNumber=4;}
	return KeyNumber;
}
void Key_Loop(void)
{
	static unsigned char NowState,LastState;
    LastState=NowState;
    NowState=Key_GetState();
	if(LastState && !NowState)  //此处是松手检测的因此刚好可以将Long_Press置一
	{   
		Key_KeyNumber=LastState;//一松手Long_Press就为0
		Long_Press=0;			
		if(Minor_Press>=2)
		{
			Minor_Press=0;
		}
	}
	if(LastState==1 && NowState)
	{   
		Countint1++;           //未松手状态
		if(Countint1>=50)
		{   
			Countint1=0;
			Long_Press=1;
		}
	}
	if(LastState==2 && NowState)
	{
		First=200;             //第一次按下需要的时间80ms
		Second=80;  	   	   //也可以直接对按键值进行检测更加正确
		Countint2++;		   //需要对两次按下进行不同的处理
		if(Countint2>=First && Minor_Press==0)
		{   
			Countint2=0;       //一直按下也会触发count--;
			Minor_Press++;     //两次按下但是时间短的长按也能实现题目效果
		}
		if(Countint2>=Second && Minor_Press==1)
		{   
			Countint2=0;
			Minor_Press++;
		}
	}
}

Nixie数码管部分

#include <REGX52.H>
#include "Delay.h"

unsigned char Nixie_Buf[9]={10,10,10,10,10,10,10,10,10};//此函数调用NixieTable()函数Nixie_Loop中调用
//第十位即为不显示为0x00

unsigned char NixieTable[13]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40,0x08};
//点才是第一个然后往后推
//.,g,f,e,d,c,b,a,//0到9,不显示,显示中间一段,显示底下一段

void Nixie_SetBuf(unsigned char Location,Number)//配置数码数组
{
	Nixie_Buf[Location]=Number;//制位Nixie_Buf
}

void Nixie_Scan(unsigned char Location,Number)//数码管需要循环扫描才能正常显示
{
	P0=0x00;//清零 消影 单片机运行速度过快防止数据串到下一个数据位
	switch(Location)位选
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;//7
		case 2:P2_4=1;P2_3=1;P2_2=0;break;//6
		case 3:P2_4=1;P2_3=0;P2_2=1;break;//5
		case 4:P2_4=1;P2_3=0;P2_2=0;break;//4
		case 5:P2_4=0;P2_3=1;P2_2=1;break;//3
		case 6:P2_4=0;P2_3=1;P2_2=0;break;//2
		case 7:P2_4=0;P2_3=0;P2_2=1;break;//1
		case 8:P2_4=0;P2_3=0;P2_2=0;break;//0
	}
	P0=NixieTable[Number];//段选
}

void Nixie_Loop(void)     //2ms调用
{
	static unsigned char i=1;	//定时器充当Delay的角色 充分显示
	Nixie_Scan(i,Nixie_Buf[i]); //NixieScan才为真正的显示
	i++;						//刷新值显示放入Nixie_Scan
	if(i>=9){i=1;}
}

Show函数

#include <REGX52.H>
#include "Nixie.h"

//主要是用来将三位数的百位十位各位分开的
//如果位数小于三位缺失位则为零

extern unsigned char bai,ge,shi;
void ShowNum(unsigned char Num)
{
	bai=Num/100;shi=Num/10%10;ge=Num%10;
	Nixie_SetBuf(1,bai);
	Nixie_SetBuf(2,shi);
	Nixie_SetBuf(3,ge);
}

如果对于定时器扫描按键的方法还不是非常熟悉

可以参考下面的文章

https://blog.csdn.net/2301_79690545/article/details/135038604?spm=1001.2014.3001.5501

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值