你好 已看了楼上两位的回答,都对你的程序用心思考了,按键延时及长短功能的程序处理不是很难,你问题中提到“下面这个是我写的一个按键扫描函数,这个放在定时器中断函数里面,定时器每隔5ms进入一次中断函数,其中key是单片机IO口,连接的按键,按下为低电平。”根据你的程序结构,你是在定时器中断里面处理的,就是在定时器中断时调用一下键盘子程序,这样问题就出来了:键盘检测的消抖一般都是10ms,你的中断为5ms,这个就需要两次中断才能完成,结合你还要完成长短检测,需要进入中断的次数更多,这就需要在中断服务退出时做好状态标志,下次进入时,先检测标志,再进行操作,如果中断服务,还有其他的功能要处理,就更要协调好各个功能的标志及状态,否则就会一个正常,一个不正常。如果你只是在定时器中断中只处理键盘功能,一个是如上面说的做好标志,一个是中断只负责检测有键按下(定时扫描),一旦有键盘按下,则关闭定时器服务,转入查询,并作出相应处理,完成后,重新开启定时器。总之你现在的程序是5ms中断程序,和键盘程序没有协调好。另:在不需要精确定时的情况下,尽量加长定时器的中断间隔,减少对主程序(背景程序)的打断;在定时器中断服务中,只完成最主要的功能操作,其他的都放在背景程序执行。我这里目前也没有相似的程序,学习还得靠自己,有什么问题在提吧。
当按键按下持续3s的时候,KeyCount=0已经执行了,并且modes=3;,但是你这时按键没有松开,她又会进入if(key==0)又执行 KeyCount++;所以当你放开时 KeyCount不为零。可以这样改
void KeyScan()
{
static unsigned int KeyCount=0;
static unsigned char modes=0;
if(key==0)
{
if(KeyCount<600)
KeyCount++;
}
else
{
if(KeyCount>=600)//长按键
modes=3;
else if(KeyCount>=20) //短按键
{
modes++;
if(modes>=3)
modes=0;
}
KeyCount=0;
}
}
这个程序我没有调试过,肯呢过存在一定问题,有问题可以追问
当我按键按下持续3s的时候,为什么KeyCount=0语句没有执行,而它后面的if(key==0) modes=3;执行成功?==>KeyCount=0语句执行了,执行之后完成了,你还没放手,所以又执行下面的了。