请教由独立键盘程序联想到的中断概念

2019-03-24 19:15发布

郭天祥教程的练习题,三个独立键盘实现按下第一个时计时停止,按下第二个时计时开始,按下第三个是计数值清零从头开始。这是我自己编的程序,可以正常实现功能。但是我在自己调试程序排错的时候,想到了中断的概念。比如这里按key3键是计数值从0开始显示,我在想如果定时器中断时间到,刚好在bb=0;bai=bb/100;shi=bb%100/10;ge=bb%10;这几句话后面进入中断程序(程序中用红 {MOD}标出了),进入中断后,bb被加到1,中断程序执行完回到主程序,此时个,十,百位分别是1,0,0,这样不是和我们程序的要求不一致了么(程序要求复位从0开始计时)。但是我把程序下载到板子上面没有出现按key3是1的情况,都是符合题目要求的0。请前辈指点,我的概念哪里出错了? #include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
sbit key2=P3^5;
sbit key3=P3^6;
sbit key4=P3^7;
unsigned char aa,ge,shi,bai;
unsigned int bb;
void init();
void display(unsigned char,unsigned char,unsigned char);
void delay(unsigned int);
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void main()
{
 init();
 while(1)
 {
 if(key1==0)
 {
  delay(5);
  if(key1==0)
  {
   TR0=0;
  }
 }
 if(key2==0)
 {
  if(key2==0)
  {
   TR0=1;
  }
 }  
 if(key3==0)      
 {
  bb=0;
  bai=bb/100;
  shi=bb%100/10;
  ge=bb%10;       //如果在这句话后,定时器中断定的时间到,进入定时器中断,那么bb被加1,个位被刷新为1,此时这个复位键复位到的是1??那么数码管也显示1?和要求不符,但实际下载程序到板子上的结果却是每次按这个键下去都是复位到0.
  if(key1==1){TR0=1;}
 }
 display(bai,shi,ge);
 }
}
void init()                         //初始化函数
{ wela=1;
 P0=0xff;
 wela=0;
 dula=1;
 P0=0x00;
 dula=0;
 aa=0;
 bb=0;
 P3=0xff;
 TMOD=0x01;
 TH0=(65536-10000)/256;
 TL0=(65536-10000)%256;
 EA=1;
 ET0=1;
 TR0=1;
}
void timer0() interrupt 1              //定时器0中断
{
 TH0=(65536-10000)/256;
 TL0=(65536-10000)%256;
 aa++;
 if(aa==1)
 {
  aa=0;
  bb++;
 }
 bai=bb/100;
 shi=bb%100/10;
 ge=bb%10;
 if(bb==999)
 {
  bb=0;
 }
}
void display(unsigned char one,unsigned char two,unsigned char three)       //显示函数
{
 dula=1;
 P0=table[one];
 dula=0;
 P0=0xff;
 wela=1;
 P0=0xfe;
 wela=0;
 delay(1);  dula=1;
 P0=table[two];
 dula=0;
 P0=0xff;
 wela=1;
 P0=0xfd;
 wela=0;
 delay(1);  dula=1;
 P0=table[three];
 dula=0;
 P0=0xff;
 wela=1;
 P0=0xfb;
 wela=0;
 delay(1);
}
void delay(unsigned int z)       //延时程序
{
 unsigned int x,y;
 for(x=z;x>0;x--)
  for(y=110;y>0;y--);
} 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
qrswll
1楼-- · 2019-03-25 05:46
顶起来
qrswll
2楼-- · 2019-03-25 06:41
辛昕
3楼-- · 2019-03-25 09:48
LZ,你的程序能正常运行么,就是实现那三个按键的正常功能。

另外,你在开头基本把问题说明白了,但是,有点乱,有个小建议,每个函数前面大致注释一下这个函数的功能。
形参 和 返回值,这样方便看。

另外就是你这个程序有的地方写得很莫名其妙,还没全找,只是看到一个地方——先不说全局变量 延时那些。

比如你的定时中断里,你要对bb计数,你就直接计数bb,何必再来一个aa等1再清零的多余动作?
辛昕
4楼-- · 2019-03-25 10:28
你得考虑很有道理,但是,从我看这个程度的角度来看,是因为你按KEY1 KEY2这两个动作,KEY1是关定时器,KEY2是开定时器,也许是因为你在这之前有过一个KEY1关定时器的动作,所以既然关了,也就不会再计数。

建议下次用 代码 这个工具来贴代码,我刚才就差点看错行了,以为是 要在KEY1有动作的情况下才刷新数码管
辛昕
5楼-- · 2019-03-25 14:32
 精彩回答 2  元偷偷看……
qrswll
6楼-- · 2019-03-25 20:22

原帖由 辛昕 于 2012-4-13 09:26 发表 额,更可能的原因是,根本没到定时器来加1,你复位后到显示这段时间里,根本还没来一次定时器。你的定时器长度是 10000,晶振是多少?定时长度是多久? 从你的主程序来看,比较简单,整个执行过程很可能才上百 ...
非常感谢前辈的指点。

1.前辈在第一条回复中说的对,我那个aa纯属多余,现在总结起来是自己陷入了思维定势,一般定时时间长的时候总是设一个中间变量,但是这里需要的是1%S,所以就不需要了。同时我这样贴代码确实是有问题的,昨天我也看了一些专业人士写的代码,注释很全,很规整,下次问问题的时候我会把代码写得更加规范。

 

2.前辈的第二条回复解决了我疑惑中的其中一种情况:按下key1后,再按key3复位。因为之前按下key1,定时器已经被关掉,所以按key3的时候肯定是0,不会往上加。

 

3.我用的晶振是11.0592MHz,定时器长度是10ms~     我的疑惑中的另一种情况是,没有按下key1,直接按key3的复位。我仔细想了一下这种情况,如果我按住key3不松手(中断结束了我还没松手),那么主程序因为while(1);循环执行,根据程序长度和机器周期,每循环一次的时间是us级的(不包括display),所以即使某一次中断刚好进入了 bai=bb/100; shi=bb%100/10; ge=bb%10;的后面,将bb变成1,可是由于key3键我还没松手,循环一次之后,bb又变成0,0----1-----0,数字变化中间间隔us级是非常短的,人眼察觉不到。

如果刚好发生了非常小概率的事件:

  bb=0;
  bai=bb/100;
  shi=bb%100/10;
  ge=bb%10;

这段之后进入中断,无论是在中断结束刚好松手key3,还是中断正在进行时松手key3,中断程序依旧执行至结束,回到主程序后,执行 if(key1==1){TR0=1;},显示1,过10ms显示2,依次递增。这时候好像就不符合要求了(从1开始复位的)。。。不过这个概率好像很小。。。?

以上是我的一些理解,可能逻辑上存在一些错误。。。还请前辈指正。。。

前辈的第三个回复:当定时器长度和这个时间(程序执行时间)相比而言差别比较大时,你的这种考虑就不可能出现。

我有些理解不过来。。。为什么定时器长度和程序执行时间相差较大的时候,我这种情况就不会出现呢?中断不会进入 bai=bb/100; shi=bb%100/10; ge=bb%10;的后面么?

 

[ 本帖最后由 qrswll 于 2012-4-14 09:16 编辑 ]

一周热门 更多>