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

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-27 07:45
原帖由 辛昕 于 2012-4-19 02:08 发表 U8 ClearFlag; //我说的那个标志 U8 Counter; //你想要的那个计数器 /* Operation on read out ClearFlag from EEPROM */ if(ClearFlag != 0x55) { Counter = 0; ClearFlag = 0x55; /* Operation on ...
  1. #include<reg52.h>
    sbit dula=P2^6; //数码管段选
    sbit wela=P2^7; //数码位选选
    sbit SDA=P2^0; //IIC数据线
    sbit SCL=P2^1; //IIC时钟线
    unsigned char aa,bb,shi,ge,flag,num1;
    //-------数码管数字显示表----//
    unsigned char code table[]={
    0x3f,0x06,0x5b,0x4f,
    0x66,0x6d,0x7d,0x07,
    0x7f,0x6f,0x77,0x7c,
    0x39,0x5e,0x79,0x71};
    //------uS级延时函数----//
    void delay()
    {;;}
    //-----mS级延时函数----//
    void delay1(unsigned char x)
    {
    unsigned char a,b;
    for(a=x;a>0;a--)
    for(b=100;b>0;b--);
    }
    //--------IIC总线函数----//
    void start() //IIC总线起始
    {
    SDA=1;
    delay();
    SCL=1;
    delay();
    SDA=0;
    delay();
    }
    void writebyte(unsigned char writedata) //IIC写字节
    {
    unsigned char temp,i;
    temp=writedata;
    for(i=0;i<8;i++)
    {
    SCL=0;
    delay();
    temp=temp<<1;
    SDA=CY;
    delay();
    SCL=1;
    delay();
    }
    SCL=0;
    delay();
    SDA=1;
    delay();

    }

    unsigned char readbyte() //IIC读字节
    {
    unsigned char i,j;
    for(i=0;i<8;i++)
    {
    SCL=0;
    delay();
    j=(j<<1)|SDA;
    delay();
    SCL=1;
    delay();
    }
    return j;

    }
    void ACK() //IIC应答
    {
    unsigned char i;
    SCL=0;
    delay();
    if(SDA==1&&i<250)
    {
    i++;
    }
    SCL=1;
    delay();
    SCL=0;
    delay();
    }
    void stop() //IIC总线结束
    {
    SDA=0;
    delay();
    SCL=1;
    delay();
    SDA=1;
    }

    //-------数码管显示函数--------//
    void display(unsigned char one,unsigned char two)
    {
    if(bb==1)
    {
    P0=0x00; //消隐
    dula=1;
    P0=table[one];
    dula=0;
    P0=0xff;
    wela=1;
    P0=0xfe;
    wela=0;
    }
    if (bb==2)
    {
    dula=1;
    P0=table[two];
    dula=0;
    P=0xff;
    wela=1;
    P0=0xfd;
    wela=0;
    bb=0;
    }
    }
    //---------初始化函数----------//
    void init()
    {
    TMOD=0x11; //开定时器0和1
    TH0=(65536-10000)/256;
    TL0=(65536-10000)%256;
    TH1=(65536-1000)/256;
    TL1=(65536-1000)%256;
    EA=1;
    ET0=1;
    ET1=1;
    TR0=1;
    TR1=1;

    start(); //读EEPROM的0x03地址空间,即标志位的值存放的空间
    writebyte(0xa0);
    ACK();
    writebyte(0x03);
    ACK();
    start();
    writebyte(0xa1);
    ACK();
    flag=readbyte();
    stop();

    if(flag!=0x99) //标志位flag,判断,如果是第一次上电,给0x08地址初始化值0x00;疑问发源地2。
    {
    start();
    writebyte(0xa0);
    ACK();
    writebyte(0x08);
    ACK();
    writebyte(0x00);
    ACK();
    stop();

    delay1(10);

    start(); //同时给标志位flag赋值=判断的值,防止下次上电再初始化00.
    writebyte(0xa0);
    ACK();
    writebyte(0x03);
    ACK();
    writebyte(0x99); //标志位的判断换成0x96,0x94之类的都会有BUG,重新上电后总是从23开始计数
    ACK();
    stop();

    }

    start(); //如果不是第一次上电,则读取0x08里面的值num1(0x08是真正数据存储地址,不是标志位地址)
    writebyte(0xa0);
    ACK();
    writebyte(0x08);
    ACK();
    start();
    writebyte(0xa1);
    ACK();
    num1=readbyte();
    stop();
    }
    //-----主函数--------//
    void main()
    {
    init();
    while(1)
    {
    start(); //每执行一次while循环都把计数值num1写入0x08地址中,方便重新上电后读取,继续计数。
    writebyte(0xa0);
    ACK();
    writebyte(0x08);
    ACK();
    writebyte(num1);
    ACK();
    stop();
    shi=num1/10; //两位数码管十位个位值的计算
    ge=num1%10;
    display(shi,ge);
    }
    }
    //-----定时器0中断,负责计数值加加以及清零-----//
    void timer0 () interrupt 1
    {
    TH0=(65536-10000)/256;
    TL0=(65536-10000)%256;
    aa++;
    if(aa==100)
    {
    aa=0;
    num1++;
    }
    if(num1>=100) //疑问发源地1。。。
    {
    num1=0;
    }
    }
    //-----定时器1中断,负责数码管现实中需要的延时,满足视觉暂留------//
    void timer1 () interrupt 3
    {
    TH1=(65536-1000)/256;
    TL1=(65536-1000)%256;
    bb++;
    }
复制代码 [ 本帖最后由 qrswll 于 2012-4-20 10:10 编辑 ]

一周热门 更多>