没有各位想的那么复杂,一个While循环搞定 |
我不知道你是学生还是已经在工作了, 如果是学生的话还可以理解.如果是出来工作了不应该一个按键的长短按还弄不清楚啊. 我给你一个程序,上面的注释很清楚 ,如果你还不理解的话就不要做单片机了.这个是我所有项目都那样写的. 有三个点要注意: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) // 读取上面短按标志位 { // 自己添加功能 } } |
daiya 发表于 2020-7-1 18:44 3秒和1秒,这么精准的吗? 我按两秒会怎么样?按4秒怎么样? 就不能多弄按键复用吗?按键扫描和处理都要时间,人手按键时间也不精准啊,谁也保证不了。 if(按下按键) { 延时500毫秒; if(按键松开)//单击 { 功能1; } else//长按 { 延时500毫秒; if(按键松开) { 功能2; } 延时1500毫秒; else { 功能3; } } } |
给你写一个短、中、长按键示例,具体任务自行完善。有详细注释,不难理解。
|
这是一个已经验证过的汇编程序,双击和长按是开关机,短按是功能切换,你参考一下,如果不会汇编,那就没有办法了
![]() |
gl960530484 发表于 2020-7-1 17:58 按下按键超过3秒就认为是已经达到开机或者其它功能的条件了,然后就调用处理程序,处理玩之后再回来判断按键有没有松开,没有松开就一直等到它松开再进行下一次的检测,这样就不会出现一直按下按键就一直有功能的现象了,我会上传一个LED灯的程序,你试着看一下,我用的是汇编,你要是不会汇编,那就没有办法了 |
按键按下去开始计时 松开按键返回时间 (这里 需要用到电平反转 中断 启用定时器 实际上就是 一键多功能 的实现 你可以查查 , ) tiime = duqu_k1_time(); //读取定时中断中按键按下去的时间 switch(time) { case 1: //处理1s 的功能代码 baeak; case 2: //处理2s 的功能代码 break; case 3: //处理3s 的功能代码 break; default: //处理不再按键保持时间功能 break; } //伪代码 |
根本不能在按键松开时判断,因为这样无法实现达到三秒立即进入“初始设定菜单”, |
Y_G_G 发表于 2020-7-1 17:13 按键1秒以上退出“初始设定菜单”,即使按键超过3秒也不会再次触发出现“初始设定菜单”,这是个难点,我曾经在手电筒上见识过类似的设置,一直没能实现,所以反复的发帖,想找到一个编程的方法 回 |
可是仪表要求的是,按键1秒以上退出“初始设定菜单”,即使按键超过3秒也不会再次触发出现“初始设定菜单”,这是个难点,我曾经在手电筒上见识过类似的设置,一直没能实现,所以反复的发帖,想找到一个编程的方法 |