单片机AT89C52定时器中断在lcd1602上实现六十秒倒计时(精确到两位小数)

在keil中编译好代码后,我用proteus仿真。
仿真结果是倒计时的代码我能实现。
但屏幕上的60秒倒计时实际上花了七十多秒。

(三个灯是用定时器中断实现不同闪烁周期,不用管)
(lcd的第二行我打了一串数字,也不用管)
(时间的误差应该主要是以为print()函数调用的延时函数,但我不知道有什么改的方法。)

#include<reg52.h>
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
bit fg_1s=0;
sbit led1=P2^3;
sbit led2=P2^4;
sbit led3=P2^5;
    int num,t;//定义秒数,倒计时个位
    static n=6;//定义倒计时的十位
    static unsigned char time_1s=0;
    void delay()//延时函数
    { int i,j;
        for(i=0;i<1;++i)
        {
            for(j=0;j<1;++j)
            {
                ;
            }
        }
    }
     void lcd_writecom(unsigned char com)//lcd写入指令
    {
        RS=0;
        RW=0;
        E=0;
        P0=com;
        delay();
        E=1;
        delay();
        E=0;
    }
    void lcd_writedata(unsigned char dat)//lcd写入数据
    {
        RS=1;
        RW=0;
        E=0;
        P0=dat;
        delay();
        E=1;
      delay();
        E=0;
    }
    void lcd_init()//lcd初始化
    {
        lcd_writecom(0x38);
        delay();
        lcd_writecom(0x38);//开启显示模式
        lcd_writecom(0x0C);//开显示不显示光标
        lcd_writecom(0x06);//指针自动加一
        lcd_writecom(0x01);//清屏
        lcd_writecom(0x80);//设置数据指针起点
    }
    void print(unsigned char a,unsigned char t)//写入指令,数据
    {
        lcd_writecom(a|0x80);
        lcd_writedata(t);
    }
    void initT0()//定时器T0初始化
    {
        TMOD=0X01;//T0工作方式2
        TH0=(65536-9216)/256;//装入初值
        TL0=(65536-9216)%256;//溢出周期为10ms
        EA=1;//打开总中断
        ET0=1;//打开定时器T0中断
        TR0=1;//T0开始计数
    }
    void main()//主函数运算
    { lcd_init();//lcd初始化
        initT0();//定时器T0初始化
        while(1)//稳定
        {    
        if(fg_1s==1)
                    {
                        fg_1s=0;
                        num++;//统计秒数
              t=1-num%10;//倒计时个位
       if(t<0)//防止负数情况
       {
         t=t+10;
             }
       if(num%10==2)//让十位退位
       {
                 n--;
             }
            print(0x80,n+0x30);//显示倒计时
              print(0x81,t+0x30);
              print(0x40,2+0x30);//显示学号
                print(0x41,0+0x30);
                print(0x42,2+0x30);
                print(0x43,1+0x30);
                print(0x44,2+0x30);
                print(0x45,1+0x30);
                print(0x46,6+0x30);
                print(0x47,7+0x30);
                print(0x48,8+0x30);
                print(0x49,7+0x30);
                 
             
                    }
         
    }
}
            
    
        

    void timer0() interrupt 1
        {static  time_200ms=0;//定义静态变量
         static  time_500ms=0;
         static  time_1000ms=0;
            
            
         TH0=(65536-9216)/256;//重新装入初值
         TL0=(65536-9216)%256;//溢出周期为10ms
            time_1s++;//计时器计数
            time_200ms++;//变量计数加1
          time_500ms++;
          time_1000ms++;
            if(time_200ms==20)//时间达到200ms
         {
             time_200ms=0;
             led1=~led1;
         }
         if(time_500ms==50)//时间达到500ms
         {
             time_500ms=0;
             led2=~led2;
         }
         if(time_1000ms==100)//时间达到1000ms
         {
             time_1000ms=0;
             led3=~led3;
         }
            if(time_1s==100)//1s
            {
                time_1s=0;
                fg_1s=1;
              
        if(num==61)//到达60秒
            {
                
                while(1)
                {
                
        lcd_writecom(0x01);//清屏
                }                    
            }
        }
    }
             

timer0 中断程序需要重写,计时逻辑混乱。lcd_writecom 不该在定时器中断中调用,应该放在 main 中。

只写了main,和 中断 timer0
别的程序照旧,程序没做过编译,可能有错,自己调下吧


void main()//主函数运算
{
    lcd_init();//lcd初始化
    initT0();//定时器T0初始化
    num = 60*100;
    unsigned char a,b,c,d;
    while(1)//稳定
    {    
        a = num/1000;
        b = (num/100)%10;
        c = (num/10)%10;
        d = (num/1)%10;
        
        print(0x80,a+0x30);//显示倒计时
        print(0x81,b+0x30);
        print(0x40,':');
        print(0x41,c+0x30);
        print(0x42,d+0x30);
        print(0x43,1+0x30);
        print(0x44,2+0x30);
        print(0x45,1+0x30);
        print(0x46,6+0x30);
        print(0x47,7+0x30);
        print(0x48,8+0x30);
        print(0x49,7+0x30);
    }
}

void timer0() interrupt 1
{
    static int time_200ms=0;//定义静态变量
    static int time_500ms=0;
    static int time_1000ms=0;

    TH0=(65536-9216)/256;//重新装入初值
    TL0=(65536-9216)%256;//溢出周期为10ms
    time_1s++;//计时器计数
    time_200ms++;//变量计数加1
    time_500ms++;
    time_1000ms++;
    
    if(num >0)    num--;
    
    if(time_200ms>=20)//时间达到200ms
    {
    time_200ms=0;
    led1=~led1;
    }
    if(time_500ms>=50)//时间达到500ms
    {
    time_500ms=0;
    led2=~led2;
    }
    if(time_1000ms>=100)//时间达到1000ms
    {
    time_1000ms=0;
    led3=~led3;
    }

}