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

江科大学长又发布了第二期的编写技巧!

大家可以看看: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代码:

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];
	}
 }
}
``
相关推荐
章鱼哥嵌入式开发2 小时前
# STM32F103 SD卡读写程序
stm32·单片机
学生哥-_-13 小时前
STM32通过KEIL pack包轻松移植LVGL,并学会使用GUI guider
stm32·lvgl·tftlcd·gui guider·gt911
三三十二13 小时前
STM32实战:数字音频播放器开发指南
stm32·单片机·嵌入式硬件
木子单片机17 小时前
基于STM32语音识别柔光台灯
stm32·单片机·嵌入式硬件·proteus·语音识别·keil
lingzhilab20 小时前
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
stm32·嵌入式硬件·信息可视化
lixzest1 天前
Keil调试模式下,排查程序崩溃简述
stm32·单片机
可乐鸡翅好好吃2 天前
通过BUG(prvIdleTask、pxTasksWaitingTerminatio不断跳转问题)了解空闲函数(prvIdleTask)和TCB
c语言·stm32·单片机·嵌入式硬件·bug·keil
广药门徒2 天前
我认为STM32输入只分为模拟输入 与 数字输入
stm32·单片机·嵌入式硬件
早睡的叶子2 天前
proteus8安装教程
stm32·嵌入式硬件