/*== ========================/*功能:单击 */ =================================*/
void key_det(void)
{
if(key_1 == 0) //按下
{
if(++key_cnt>6) //主循环10ms进来一次 作用:按下消抖
{
if(key_flag == 0) //防止重复进入
{
key_flag = 1;
led_1 = ~led_1; //单击事件
}
}
}
else //松开
{
if(key_cnt >= 6) key_cnt = 6;
if(key_cnt != 0) --key_cnt;//防止松开抖动
if(key_cnt == 0) //防止重复进入
{
if(key_flag)
{
key_flag = 0;
}
}
}
}
/*=============================/* 单击 双击 */================================*/
void key_det_2(void)
{
if(click_flag) //单击
{
click_flag = 0;
led_1 = ~led_1;
}
if(double_click_flag) //双击
{
double_click_flag = 0;
led_2 = ~led_2;
}
if(key_1 == 0) //按下
{
if(++key_cnt_2 > 6)//主循环10ms进来一次 作用:按下消抖
{
key_double_click_cnt = 0;
if(key_flag_2 == 0) //防止重复进入
{
key_flag_2 = 1;
}
else if(key_flag_2_1 == 1)
{
key_flag_2_1 = 0;
double_click_flag = 1; //300ms以内再次按下就判断为 双击事件
key_double_flag = 1; //该标志位置1 为了不触发单击
key_flag_2 = 0;
}
}
}
else
{
if(key_flag_2) //防止重复进入
{
key_flag_2_1 = 1;
if(++key_double_click_cnt >= 30) //300ms 双击间隔时间改这里
{
key_double_click_cnt = 0;
if(key_double_flag == 0)
{
click_flag = 1; //300ms以内没有再次按下按键就判断为 单击事件
}
key_flag_2_1 = 0;
key_double_flag = 0;
key_flag_2 = 0;
}
}
}
}
/*=============================/* 单击 长按*/================================*/
void key_det_3(void)
{
if(key_flag_1) //单击 亮灭led_1
{
key_flag_1 = 0;
led_1 = ~led_1;
}
if(key_long) //长按 亮灭led_2
{
key_long = 0;
led_2 = ~led_2;
}
if(key_1 == 0) //按下
{
if(++key_cnt > 6) //主循环10ms进来一次 作用:按下消抖
{
if(key_flag == 0 && key_long_flag == 0) //防止重复进入
{
key_flag = 1;
}
if((++key_cnt_1 > 200) && key_long_flag == 0) //长按时间
{
key_cnt_1 = 0;
key_flag = 0; //防止触发单击
key_long = 1; //长按事件
key_long_flag = 1;
}
}
}
else
{
if(key_cnt >= 6) key_cnt = 6;
if(key_cnt !=0) --key_cnt;
key_long_flag = 0;
key_cnt_1 = 0;
if(key_cnt == 0)
{
if(key_flag) //防止重复进入
{
key_flag = 0;
key_flag_1 = 1; //单击事件
}
}
}
}
以下两种写法:适用于一个按键实现多种功能、简单易懂、移植性高修改性高、可以运用到实际的项目开发
/*===========================/* 单击 双击 长按 */=============================*/
void key_det_1(void)
{
if(key_flag_1 == 1) //单击
{
key_flag_1 = 0;
led_1 = ~led_1;
}
else if(key_flag_1 == 2) //双击
{
key_flag_1 = 0;
led_2 = ~led_2;
}
else if(key_flag_1 == 3) //长按
{
key_flag_1 = 0;
led_3 = ~led_3;
}
switch(key_state)
{
case 0:
if(key_1 == 0) //按下
{
if(++key_cnt_1 > 6) //主循环10ms进来一次 作用:按下消抖
{
key_cnt_1 = 0;
key_state = 1;
}
}
else
{
key_cnt_1 = 0;
}
break;
case 1:
if(key_1 == 1) //松开
{
key_cnt_1 = 0;
key_state = 2;
// key_flag_1 = 1; //单击判断不能放这里,不然会触发单击和双击
return;
}
if(++key_cnt_1 >= 200) //主循环10ms进来一次 = 2S
{
key_cnt_1 = 0;
key_state = 3;
key_flag_1 = 2; //长按事件
return;
}
break;
case 2:
if(key_1 == 0) //按下
{
key_cnt_1 = 0;
key_state = 3;
key_flag_1 = 3; //双击判断
return;
}
if(++key_cnt_1 >= 40) // 计时超过400ms判断为单击事件
{
key_cnt = 0;
key_flag_1 = 1; //单击事件
key_state = 3;
return;
}
break;
case 3:
if(key_1 == 1) //松开
{
key_state = 0;
}
break;
default:
key_state = 0;
}
key_flag_1 = 0;
}
/*======================== /* 单击 双击 长按 三击*/ ===========================*/
void key_det_1_1(void)
{
if(key_flag_1 == 1) //单击
{
key_flag_1 = 0;
led_1 = ~led_1;
}
else if(key_flag_1 == 2) //双击
{
key_flag_1 = 0;
led_2 = ~led_2;
}
else if(key_flag_1 == 3) //长按
{
key_flag_1 = 0;
led_3 = ~led_3;
}
else if(key_flag_1 == 4) //三击
{
key_flag_1 = 0;
led_4 = ~led_4;
}
switch(key_state)
{
case 0:
if(key_1 == 0) //按下
{
if(++key_cnt_1 > 6) //主循环10ms进来一次 作用:按下消抖
{
key_cnt_1 = 0;
key_state = 1;
}
}
else
{
key_cnt_1 = 0;
}
break;
case 1:
if(key_1 == 1) //松开
{
key_cnt_1 = 0;
key_state = 2;
// key_flag_1 = 1; //单击判断不能放这里,不然会触发单击和双击
return;
}
if(++key_cnt_1 >= 200) //主循环10ms进来一次 = 2S
{
key_cnt_1 = 0;
key_state = 5;
key_flag_1 = 2; //长按事件
return;
}
break;
case 2:
if(key_1 == 0) //按下
{
key_cnt_1 = 0;
key_state = 3;
return;
}
if(++key_cnt_1 >= 40) // 计时超过400ms判断为单击事件
{
key_cnt = 0;
key_state = 5;
key_flag_1 = 1; //单击事件
return;
}
break;
case 3:
if(key_1 == 1) //松开
{
key_cnt_1 = 0;
key_state = 4;
return;
}
if(++key_cnt_1 >= 40) // 计时超过400ms判断为双击事件
{
key_cnt = 0;
key_state = 5;
key_flag_1 = 3; //双击事件
return;
}
break;
case 4:
if(key_1 == 0) //按下
{
key_cnt_1 =0;
key_state = 5;
key_flag_1 = 4; //三击事件
return;
}
if(++key_cnt_1 >= 40) // 计时超过400ms判断为双击事件
{
key_cnt = 0;
key_state = 5;
key_flag_1 = 3; //双击事件
return;
}
break;
case 5:
if(key_1 == 1) //松开
{
key_state = 0;
}
break;
default:
key_state = 0;
}
key_flag_1 = 0;
}
/*=======================================================================*/
以上几种按键的写法是利用上班摸鱼时间整理出来的所以函数和变量的命名比较随意。
希望这篇文章能帮助到各位,如有更好的写法可以互相学习交流一下。
从事单片机软件开发大半年的小白