
Keil C 中的关于中断程序退出状态问题
想完成如下功能:按9次按键,P1对应显示按键次数(二进制数)。当按第10下时,正常退出INT0程序,打开TIMER0,LED能正常闪烁。可是如果我在INT0的最后不加延时...
想完成如下功能:按9次按键,P1对应显示按键次数(二进制数)。当按第10下时,正常退出INT0程序,打开TIMER0,LED能正常闪烁。
可是如果我在INT0的最后不加延时delay(200)时,程序当按第10下时,P1端口却直接显示1了(应该显示10)。原先以为程序在跳出while时、结束中断时,检测到MODE是低电平,会再次触发INT0,可是我增加了for(;;)当按钮松掉时,离开INT0中断,还是不行。不知道为什么,请高手帮忙解答。
程序清单、仿真图如下
#include <at89x51.h> #include <intrins.h> unsigned char data sec100; unsigned char data flag;bit vkey,skey; sbit MODE=P2^6;sbit BLINK = P3^7;sbit LED = P2^3;
void delay(unsigned char ms) { while(ms--) {unsigned char i; for(i = 0; i< 250; i++); } }
void timer0() interrupt 1 { TH0=0xdc;TL0=0x00; //(f0=11.0592Mhz) sec100++;
if(sec100 >= 50){sec100 = 0;BLINK=0; delay(100);BLINK=1;} }
void int0() interrupt 0 { TR0=0; //禁止Timer0 IE=0; //禁止中断
flag=0; vkey=1; while(flag^0x0a){skey =MODE; //扫描按键状态 if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体 {delay(10); //去按键抖动 skey =MODE; //转回扫描按键状态 if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体 {vkey=skey; //将skey的值付给vkey if (skey==0) //MODE键按下 {flag++;}//调整标志位加1 } }
P1=flag; //P1实时显示flag 值}//while循环结束
//========以下两句,对结果没有影响,但理论上讲,应该是起作用的============for(skey=MODE;skey=0;delay(20),skey=MODE);//当按钮松掉时,离开INT0中断if(MODE=1)//======================================================{IE=0x8f; //CPU开中断,INT0,INT1,开中断LED=0; //TESTTR0=1; //Timer0启动}//delay(200);//这条语句写与不写结果不同. }
void main() {IE = 0x8f; //CPU开中断.IP = 0x04; //设置INT0为中断最高优先级IT0=0; //外部INT0,要求必须是电平触发方式TMOD = 0x11; TH0 = 0xdc;TL0 = 0x00;
TR0 = 1; //Timer0启动while(1); } 展开
可是如果我在INT0的最后不加延时delay(200)时,程序当按第10下时,P1端口却直接显示1了(应该显示10)。原先以为程序在跳出while时、结束中断时,检测到MODE是低电平,会再次触发INT0,可是我增加了for(;;)当按钮松掉时,离开INT0中断,还是不行。不知道为什么,请高手帮忙解答。
程序清单、仿真图如下
#include <at89x51.h> #include <intrins.h> unsigned char data sec100; unsigned char data flag;bit vkey,skey; sbit MODE=P2^6;sbit BLINK = P3^7;sbit LED = P2^3;
void delay(unsigned char ms) { while(ms--) {unsigned char i; for(i = 0; i< 250; i++); } }
void timer0() interrupt 1 { TH0=0xdc;TL0=0x00; //(f0=11.0592Mhz) sec100++;
if(sec100 >= 50){sec100 = 0;BLINK=0; delay(100);BLINK=1;} }
void int0() interrupt 0 { TR0=0; //禁止Timer0 IE=0; //禁止中断
flag=0; vkey=1; while(flag^0x0a){skey =MODE; //扫描按键状态 if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体 {delay(10); //去按键抖动 skey =MODE; //转回扫描按键状态 if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体 {vkey=skey; //将skey的值付给vkey if (skey==0) //MODE键按下 {flag++;}//调整标志位加1 } }
P1=flag; //P1实时显示flag 值}//while循环结束
//========以下两句,对结果没有影响,但理论上讲,应该是起作用的============for(skey=MODE;skey=0;delay(20),skey=MODE);//当按钮松掉时,离开INT0中断if(MODE=1)//======================================================{IE=0x8f; //CPU开中断,INT0,INT1,开中断LED=0; //TESTTR0=1; //Timer0启动}//delay(200);//这条语句写与不写结果不同. }
void main() {IE = 0x8f; //CPU开中断.IP = 0x04; //设置INT0为中断最高优先级IT0=0; //外部INT0,要求必须是电平触发方式TMOD = 0x11; TH0 = 0xdc;TL0 = 0x00;
TR0 = 1; //Timer0启动while(1); } 展开
展开全部
你的困惑根源在于对按键按下/抬起瞬间的状态认识不足。
事实上,在按键按下/抬起瞬间,按键端口上会有一个持续抖动的电平(类似于不规则锯齿波,你可以上网查找一下),因此在一段时间之内P2.6上采集的电平将是不断变化的0-1-0序列。你所增加的for(;;)只判断一种电平,所以也并不能起到去抖的作用。
一般较通用的按键处理流程是:当INT0#检测到跳变沿中断时,置一个标志,关闭EX0中断使能;主循环中凭借此标志延时20~100ms去抖(说白了就是避过按键电平不稳定的这段时间),然后重新采集P2.6状态,仍旧是低电平才判定为有效按键变化。
对于连接线较长或者易受干扰的场合,按键处理应增加至少一阶的数字滤波。
事实上,在按键按下/抬起瞬间,按键端口上会有一个持续抖动的电平(类似于不规则锯齿波,你可以上网查找一下),因此在一段时间之内P2.6上采集的电平将是不断变化的0-1-0序列。你所增加的for(;;)只判断一种电平,所以也并不能起到去抖的作用。
一般较通用的按键处理流程是:当INT0#检测到跳变沿中断时,置一个标志,关闭EX0中断使能;主循环中凭借此标志延时20~100ms去抖(说白了就是避过按键电平不稳定的这段时间),然后重新采集P2.6状态,仍旧是低电平才判定为有效按键变化。
对于连接线较长或者易受干扰的场合,按键处理应增加至少一阶的数字滤波。

2023-06-12 广告
单片机,即单片微控制器,也称为单片微型计算机,是将中央处理器(CPU)、存储器(ROM,RAM)、输入/输出接口和其他功能部件集成在一块 在一个小块的集成电路上,从而实现对整个电路或系统的数字式控制。单片机不是完成某一个逻辑功能的芯片,而是...
点击进入详情页
本回答由意法半导体(中国)投资有限公司提供
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询