单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1521|回复: 4
收起左侧

定时器中断的计时问题

[复制链接]
xzf586 发表于 2017-9-24 19:26 | 显示全部楼层 |阅读模式
定时器中断的计时问题
前些天看到一个定时器中断的计时问题,那里面采用的答案似乎是,中断执行以后才开始再次计时,对此不敢苟同,考虑以下程序,0.1秒表计时
#include<reg52.h>

unsignedchar code DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//
unsignedchar code WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedchar miao=0;

voidDelayUs2x(unsigned char t)//大致延时(2*t+5)us

{  
    while(--t);
}

voidDelayMs(unsigned int t)//大致延时1mS

{   
    while(t--)
    {         
         DelayUs2x(245);
         DelayUs2x(245);
    }
}


/*------------------------------------------------
显示函数,用于动态扫描数码管
------------------------------------------------*/
voidDisplay(unsigned char dat)
{
    P1=0xff;
    P0=DuanMa[dat%10];
    P1=0x7f;
    DelayMs(3);

    P1=0xff;
    P0=DuanMa[(dat/10)%10]|0x80;
    P1=0xbf;
    DelayMs(3);

    P1=0xff;
    P0=DuanMa[(dat/100)%10];
    P1=0xdf;
    DelayMs(3);

}

/*------------------------------------------------
                  主函数

------------------------------------------------*/
voidmain (void)
{        
    TMOD |= 0x01;                              
    TH0=(65536-2000)/256;                 
    TL0=(65536-2000)%256;   //2ms定时

    EA=1;            
    ET0=1;         
    TR0=1;                             

    while (1)        
    {         
         Display(miao);
    }
}



/*------------------------------------------------
                定时器中断子程序

------------------------------------------------*/
voidTimer0_isr(void) interrupt 1
{
    static unsigned char count=0;
    TH0=(65536-2000)/256;                 //重新赋值 2ms

    TL0=(65536-2000)%256;
    count++;
    if(count==50)
    {
          miao++;
          count=0;
    }
//    DelayMs(1);   
}

1:定时器是2MS定时,中断里面的 延时1ms DelayMs(1),去掉与加上,对计时没有影响
2:将中断程序改成
voidTimer0_isr(void) interrupt 1
{
    static unsigned char count=0;
   
    count++;
    if(count==50)
    {
          miao++;
          count=0;
    }
    DelayMs(1);   
TH0=(65536-2000)/256;                 //重新赋值 2ms

    TL0=(65536-2000)%256;
}
影响结果很大!
为了再次验证楼主的想法,干脆将中断程序改为
voidTimer0_isr(void) interrupt 1
{
    static unsigned char count=0;
    //TH0=(65536-2000)/256;                 //重新赋值 2ms

    //TL0=(65536-2000)%256;
    count++;
    if(count==50)
    {
          miao++;
          count=0;
    }
    DelayMs(1);   
}
去掉重新赋值,计时依然,但是慢了许多!
结论:
1:定时计数满了以后,模式1就是到达65536,溢出标志TF0在进入中断服务程序后,自动清零,开始下一次中断计时,计时是从中断服务程序的第一条语句开始

2:正因为1,所以进入中断后,首先是给定时器赋值,否则其从0开始计时,所以赋值的位置不对,结果差异很大

3:在中断服务程序中是不会再次进入此中断,上面DelayMs(1)延时1MS没有影响,但是一旦改成延时2ms,结果就乱了套,因此中断服务的运行时间不能超过定时器的定时时间,除非关闭中断,最后再开启中断

以上是个人想法!

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

 楼主| xzf586 发表于 2017-9-24 19:30 | 显示全部楼层
从上面可以看出,使用定时器定时也会有误差,误差的来源是:1主程序任务的保存时间,2是定时器初值的赋值时间
回复

使用道具 举报

ahshmj 发表于 2017-9-25 20:09 | 显示全部楼层
65535+1=0
65535=0xffff
0xffff+1=0x10000
由于只有16位,只能显示0x0000.

定时器根据需要设置初值,初值+延时时间=65535,如果不重新装载初值,就会从零开始。

重装初值应在中断函数的最前面,如果延时1ms再装初值,每次中断就会延长1ms。
回复

使用道具 举报

karolyte 发表于 2020-6-30 16:04 | 显示全部楼层
您好,我现在有个程序,定时器设置的定时时间是1ms,中断服务的运行时间是570us,没有超过定时时间,但是实际运行时发现没有按照设定的定时时间进入中断,它自己70ms进入一次中断,目前不知道是什么原因造成的
回复

使用道具 举报

long... 发表于 2020-6-30 16:29 | 显示全部楼层
很好,一下就说中了要点
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表