蓝桥杯嵌入式学习记录【按键】实现单击,双击,长按
按键模块的介绍及讲解,各种按键操作。
·
硬件

按键配置

简单按键函数
变量分析
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; // 更新上一次按键状态
}
更多推荐
所有评论(0)