硬件

在这里插入图片描述

按键配置

在这里插入图片描述

简单按键函数

变量分析

uint8_t B1_state;   //按键当前状态
uint8_t B1_last_state;  //按键上一状态

代码整体示例

void key_scan(void)
{
	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
	if(B1_state == 0 && B1_last_state == 1)
	//B1_state == 0 表示当前按键被按下  B1_last_state == 1 表示按键的上一次状态是未按下
	{
		count ++;  //在LCD显示
	}
	B1_last_state = B1_state;  //更新按键状态
}

读取B1按键当前状态:

HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)

如果 按键按下(低电平),返回 0。
如果 按键未按下(高电平),返回 1。

单击

uint8_t B2_state;
uint8_t B2_last_state;
void key_scan(void)
{
	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
	if(B1_state == 0 && B1_last_state == 1)
	//B1_state == 0 表示当前按键被按下  B1_last_state == 1 表示按键的上一次状态是未按下
	{
		count ++;  //在LCD显示
	}
	B1_last_state = B1_state;  //更新按键状态
}

双击

时钟配置

在这里插入图片描述
定时器时钟频率计算公式
在这里插入图片描述
溢出时间计算公式
在这里插入图片描述

变量分析

uint8_t B2_state;
uint8_t B2_last_state;

uint32_t B2_time;      //B2当前按下时间
uint32_t B2_last_time;    //B2上一次按下的时间
uint32_t click_time_B2;   //点击定时器
uint8_t click_count_B2;  //点击次数 判断是否双击
uint8_t click_flag_B2;   //点击事件标志 记录点击事件是否发生

代码整体示例

void key_scan(void)
{
	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
	//B2双击+单击
	if(B2_state == 0 && B2_last_state == 1)
	{
		B2_time = HAL_GetTick();  // 记录当前时间(毫秒)
		if(click_count_B2 && (B2_time - B2_last_time) < 300)  
		//如果两次按键间隔小于 300ms,判定为双击,count += 2。否则,暂时认为是单击,等待 handle_B2() 进一步确认。
		{
			count += 2;
			click_count_B2 = 0;   // 清空点击次数
			click_flag_B2 = 0;    // 清空点击事件标志
		}
		else
		{
			click_count_B2= 1;   // 记录单击
			B2_last_time = B2_time;  // 记录本次按下的时间
			click_flag_B2 = 1;   // 标记有点击事件
			click_time_B2 = 0;   // 计时器清零
		}
	}
	B2_last_state = B2_state;  //更新按键 B2 的上一次状态
}

void handle_B2(void)
{
	if(click_flag_B2 && click_time_B2 >= 300)
	{
		//单机操作
		count++;
		// 重置点击次数和点击标志
		click_count_B2 = 0;
		click_flag_B2 = 0;
	}
}
//下面的代码写在fun.c文件
//TIM2 定时器周期中断回调函数,1ms 触发一次
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		if(click_flag_B2)
		{
			click_time_B2++;  //计时器累加
			handle_B2();
		}

}

三击

变量分析

uint8_t B3_state;
uint8_t B3_last_state;

uint32_t B3_time;      //B3当前按下时间
uint32_t B3_last_time;    //B3上一次按下的时间
uint32_t click_time_B3;   //点击定时器
uint8_t click_count_B3;  //点击次数 (用于判断单击/双击/三击)
uint8_t click_flag_B3;   //点击事件标志 记录点击事件是否发生

代码整体示例

void key_scan(void)
{
	B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
	//B3三击+双击+单击
	if(B3_state == 0 && B3_last_state == 1)  // B3 按键按下(下降沿检测)
	{
		B3_time = HAL_GetTick();  // 记录当前时间(毫秒
		if(click_count_B3 > 0 && (B3_time - B3_last_time) < 300)
		{
			// 如果时间间隔小于 300ms,说明是连续点击,点击次数加 
			click_count_B3 ++;
			if(click_count_B3 == 3)
			{
				//三击操作
				count += 3;
				click_count_B3 = 0;  // 清空点击次数
				click_flag_B3 = 0;   // 清空点击事件标志
			}
		}
		else
		{
			click_count_B3 = 1;
		}
		B3_last_time = B3_time;   // 记录本次按下的时间
		click_flag_B3 = 1;        // 标记有点击事件
		click_time_B3 = 0;		  // 计时器清零
	}
	B3_last_state = B3_state;
}

void handle_B3(void)
{
	if(click_flag_B3 && click_time_B3 >= 300)
	{
		if(click_count_B3 == 1)
		{
			//单机操作
			count++;
		}
		else if(click_count_B3 == 2)
		{
			//双击操作
			count += 2;
		}
		// 重置点击次数和点击标志
		click_count_B3 = 0;
		click_flag_B3 = 0;
	}
}

//TIM2 定时器周期中断回调函数,1ms 触发一次
 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		if(click_flag_B3)
		{
			click_time_B3++;  // 计时器累加
			handle_B3();
		}
	}
}

长按

标志位松手检测

变量分析
uint8_t B4_state;
uint8_t B4_last_state;
uint16_t B4_press_time;   //B4持续按下时间
uint8_t B4_pressd;     //B4按下标志
代码整体示例
void key_scan(void)
{
	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);  // 读取 B4 按键状态
	// 按键按下(下降沿检测
	if(B4_state == 0 && B4_last_state == 1)
	{
		B4_pressd = 1;      // 标记按键被按下
		B4_press_time = 0;  // 按下时间清零
	}
	// 按键松开(上升沿检测)
	else if(B4_state == 1 && B4_last_state == 0)
	{
		if(B4_pressd)   // 确保之前检测到按键按下
		{
			if(B4_press_time >=1000)   // 如果按住时间 >= 1 秒
			{
				count = 0;    // 执行长按操作:清零 count
			}
			else
			{
				count ++;   // 执行单击操作:count++
			}
		}
		B4_pressd = 0;   // 清除按键按下标志
	}
	B4_last_state = B4_state;    // 更新上一次按键状态
}	

//TIM2 定时器周期中断回调函数,1ms 触发一次	
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
        //标志位松手检测
		if(B4_pressd)
		{
			B4_press_time ++;   // 每次定时器溢出,增加按住时间
		}
	}
}

长按下检测

变量分析
uint8_t B4_state;
uint8_t B4_last_state = 1;  //置1,避免提前进行松开操作
uint32_t B4_press_time;   //B4持续按下时间
代码整体示例

开启定时器中断

//开定时器中断
void key_scan(void)
{
	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);  // 读取 B4 按键状态
	if(B4_state == 0 && B4_last_state == 1)
	{
		B4_press_time = 0;  // 按键按下时,清零按下时间计数
	}
	else if(B4_state == 0 && B4_last_state == 0)
	{
		if(B4_press_time >= 1000)
		{
		// 如果按键按下时间 >= 1000(单位为毫秒),认为是长按操作
			count --;  //长按操作
		}
	}
	else if(B4_state == 1 && B4_last_state == 0)
	{	
		if(B4_press_time < 1000)
		{
		// 如果按键按下时间小于 1000,认为是单击操作
			count -= 2;  //单击操作
		}
	}
	B4_last_state = B4_state;    // 更新上一次按键状态
}	

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		//用定时器中断		
		B4_press_time ++;  // 每次定时器溢出时,增加按键按下时间计数 
	}
}

不开启定时器中断

void key_scan(void)
{
	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);  // 读取 B4 按键状态
	if(B4_state == 0 && B4_last_state == 1)
	{
		TIM3->CNT = 0;   // 清零 TIM3 定时器计数
	}
	else if(B4_state == 0 && B4_last_state == 0)
	{
		if(TIM3->CNT >= 10000)
		{
			count --;  //长按操作
		}
	}
	else if(B4_state == 1 && B4_last_state == 0)
	{	
		if(TIM3->CNT < 10000)
		{
			count -= 2;  //单击操作
		}
	}
	B4_last_state = B4_state;    // 更新上一次按键状态
}	
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐