我不知道你是学生还是已经在工作了, 如果是学生的话还可以理解.如果是出来工作了不应该一个按键的长短按还弄不清楚啊. 我给你一个程序,上面的注释很清楚 ,如果你还不理解的话就不要做单片机了.这个是我所有项目都那样写的. 有三个点要注意:1 你要用到的那个IO口,也就是按键IO口必须是输入设置,并且打开上拉,2 我的程序是4MS 一个定时. 3 不要用延时程序, 你用了延时程序以后这个就程序读取的电平就不准了, 时间也不准了.
void KEY_SCAN(void) //扫描按键
{
if(!f_key_press) //判断是按下还是弹起状态 1 按下状态 0 弹起状态
{
if(P_KEY){key_cnt=0;} // 读取IO口的电平 因为开了上拉,没有按按键的时候读取到的为高 所以只要是高就清零计数
key_cnt++; // ++
if(key_cnt>=10) // 连续读取IO口电平10次证明按下按键了, 并且稳定了这也可以理解为消抖
{
key_cnt=0; // 清零按键计数 记得你一定要清零
f_key_press=1; //置按下按键标志位 并且置长按按键标志位
f_key_ctrl=1; // 长按标志位置起来后面要用到
}
}
else //判断按键是按下还是弹起状态 按下状态 0 弹起状态
{
if(!P_KEY){key_cnt=0;} //读取IO口电平 ,开上拉的缘故 置要读取到为低就证明还在按下状态中 所以要清零按键计数
key_cnt++; //++
if(key_cnt>=10) // 连续读取到10次高电平就证明已经弹起按键了.
{
key_cnt=0; // 清零弹起计数
f_key_press=0; //清按下标志位
// 敲重点 这里仔细看
if(f_key_ctrl) //去读取这个标志位还在不在, 如果这个标志位不在就说明已经按下有3S了.直接跳过这里.执行下一条命令;
//如果这标志位还在就说明按下不到3S ,只能是短按,或者按下1S-3s之间.所以我们要来判断ctrl_cnt的个数
{
if(ctrl_cnt>=250) //判断之前的计数是多少 如果大于250*4MS =1000MS 就是长按1S的动作,那么执行长按1s的程序就可以了
{
ctrl_cnt=0; // 记得判断后要立即清零
f_key_1s=1; //和f_key_3s一样, 后面去读取这个标志位 有就执行相应动作,没有就不执行
}
else //不大于1S就短按 我们执行短按的程序
{
ctrl_cnt=0;
f_key_short=1;
}
}
//敲重点因为前面判断了f_key_ctrl标志位还在不在,所以判断完以后一定要清零 ,并且清理的位置不能错
f_key_ctrl=0; // 清零长按标志位
}
}
//
if(f_key_ctrl) // 这个长按只管3S的长按 1 S 的在弹起里面处理
{
ctrl_cnt++; // 只要一读取到f_key_ctrl为1 就开始++计数
if(ctrl_cnt>=750) //计数到750*4ms=3000ms 就清零 说明长按3S时间到了
{
ctrl_cnt=0; // 清零计数
f_key_ctrl=0; // 清零标志位
f_key_3s=1; // 这个标志位是长按3s的标志位,你自己另外写一个函数,然后来读取这个标志位 为1就执行长按3S的动作
//否则就不执行
}
}
else
{
ctrl_cnt=0;
}
}
void WORK_APP(void)
{
if(f_key_3s) //读取上面按键的标志位 3S
{
// 自己添加相应的功能
}
else if(f_key_1s) // 读取上面按键的标志位1s
{
// 自己添加功能
}
else if(f_key_short) // 读取上面短按标志位
{
// 自己添加功能
}
} |