35.成功解决编写关于“江协科技”编写技巧第二期标志位积累的问题

发布于:2025-06-07 ⋅ 阅读:(21) ⋅ 点赞:(0)

江科大学长又发布了第二期的编写技巧!
大家可以看看:https://space.bilibili.com/383400717
最后面给了一个未完成的任务:
在这里插入图片描述
这里我已经把这个问题给解决了!
总代码放在资源里面,key.c放在文章最后面!同时感兴趣的同学可以看看我的Linux驱动讲解!

1、保存上一次的标志位:

在这里插入图片描述

2、清零目标标志位

计划在同一个按键事件后的标志位发生变化时,判断上一个标志位和目前标志位不一样时进行清理:
在这里插入图片描述
为了简单理解,我们就以同一个按键,两位2进制标志位来讲。
假设上一个的标志位是10;如果按照之前的代码,切换模式的时候,那目前标志位就是11,因为假设并没有进行检查操作就想清零。解决标志位积累的问题!
所以进行:

if(Last_Key_Flag[i]!=Key_Flag[i])
{
	Key_Flag[i]&=~Last_Key_Flag[i];
}
Last_Key_Flag[i]=Key_Flag[i];

3、同一个按键空闲的时候也清零标志位:

在这里插入图片描述
这样就行了!不过这里有一个问题,就是按键松开和按压时间交替太快了,程序会认为是清零标志位,而不是双击,太慢了,就会认为是单击。但是如果不这样设置,就会保留最后一次的标志位,目前我没有想到好的方法!就留给后来者了!

4、Key.c代码:

 #include "stm32f10x.h"                  // Device header
 #include "Key.h"
 
#define KEY_PRESSED   1
#define KEY_UNPRESSED 0

#define KEY_TIME_DOUBLE 200
#define KEY_TIME_LONG   2000
#define KEY_TIME_REPEAT 100



u8 Key_Flag[KEY_COUNT];


void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef   GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;             //¶ÁÈ¡°´¼ü
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;             //¶ÁÈ¡°´¼ü
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

u8 Key_Getstate(u8 n)
{
	if(n==KEY_1)
	{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)
	{
		return KEY_PRESSED ;
	}
  }
	else if(n==KEY_2)
	{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0)
	{
		return KEY_PRESSED ;
	}
  }
	else if(n==KEY_3)
	{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==1)
	{
		return KEY_PRESSED ;
	}
	}
	else if(n==KEY_4)
	{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==1)
	{
		return KEY_PRESSED ;
	}
	}
	return KEY_UNPRESSED;
 }

u8 Key_Check(u8 n,u8 Flag)
{
	if(Key_Flag[n]&Flag)
	{
		if(Flag!=KEY_HOLD)
		{
		Key_Flag[n]&=~Flag;
    }
		return 1;
	}
	return 0;
}

void Key_Tick(void)
{
	static u8  Count,i;
	static u8  CurrState[KEY_COUNT],PrevState[KEY_COUNT];
	static u8  S[KEY_COUNT];
	static u16 Time[KEY_COUNT];
	static u8  Last_Key_Flag[KEY_COUNT]; 
	for(i=0;i<KEY_COUNT;i++)
	{
	if(Time[i]>0)
	{
		Time[i]--;
	}
 }
	Count++;
	if(Count>=20)
	{
		Count=0;
		for(i=0;i<KEY_COUNT;i++)
		{
		PrevState[i]=CurrState[i];
		CurrState[i]=Key_Getstate(i);
		if(CurrState[i]==KEY_PRESSED)
		{
			//HOLD=1
			Key_Flag[i]|=KEY_HOLD;
		}else{
			//HOLD=0
			Key_Flag[i]&=~KEY_HOLD;
		}
		if(CurrState[i]==KEY_PRESSED&&PrevState[i]==KEY_UNPRESSED)
		{
			//Down=1
			Key_Flag[i]|=KEY_DOWN;
		}
		if(CurrState[i]==KEY_UNPRESSED&&PrevState[i]==KEY_PRESSED)
		{
			//UP=1
			Key_Flag[i]|=KEY_UP;
			
		}
		if(PrevState[i]==KEY_UNPRESSED&&CurrState[i]==KEY_UNPRESSED)
		{
				Key_Flag[i]&=0x00;
		}
		if(S[i]==0)
		{
			if(CurrState[i]==KEY_PRESSED)
			{
				Time[i]=KEY_TIME_LONG;//2s³¤°´Ê±¼äãÐÖµ
				S[i]=1;
			}
		}
		else if(S[i]==1)
		{
		 if(CurrState[i]==KEY_UNPRESSED)
			{
				Time[i]=KEY_TIME_DOUBLE;
				S[i]=2;
			}
			else if(Time[i]==0)
			{
				Time[i]=KEY_TIME_REPEAT;
				//LONG=1
				Key_Flag[i]|=KEY_LONG;
				S[i]=4;
			}
		}
		else if(S[i]==2)
		{
			if(CurrState[i]==KEY_PRESSED)
			{
				//DOUBLE=1
				Key_Flag[i]|=KEY_DOUBLE;
				S[i]=3;
			}
			else if(Time>0)
			{
				//SINGLE=1
				Key_Flag[i]|=KEY_SINGLE;
				S[i]=0;
			}
		}	
		else if(S[i]==3)
		{
			if(CurrState[i]==KEY_UNPRESSED)
			{
					S[i]=0;
			}
		}		
		else if(S[i]==4)
		{
			if(CurrState[i]==KEY_UNPRESSED)
			{
					S[i]=0;
			}
			else if(Time[i]==0)
			{
				Time[i]=KEY_TIME_REPEAT;
				//REPEAT=1
				Key_Flag[i]|=KEY_REPEAT;
				S[i]=4;
			}
		}	
		if(Last_Key_Flag[i]!=Key_Flag[i])
		{
			Key_Flag[i]&=~Last_Key_Flag[i];
		}
    Last_Key_Flag[i]=Key_Flag[i];
	}
 }
}
``


网站公告

今日签到

点亮在社区的每一天
去签到