找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2227|回复: 9
打印 上一主题 下一主题
收起左侧

单片机两个定时器一块用,定时时间不准确?附源程序

[复制链接]
跳转到指定楼层
楼主
ID:1054240 发表于 2022-12-15 20:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题主要出在定时器0那里,里面所有定时操作都不准确。我定时器赋的初值是为50ms准备的,我想要定时500ms,按理说进入定时器中断10次就可以定500ms了,可是实际我烧录后,速度非常快,软件调试发现根本不到500ms,只能把判断条件改到进入定时器中断74次,调试才500ms...希望有知道的大佬解答一下。

以下是单片机代码
#include <REGX52.H>
#include <intrins.h>

typedef unsigned char u8;
typedef unsigned int u16;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

#define SMG_A_DP_PORT P0
#define LED_PORT P2

u8 gsmg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x76,0x79,0x38,0x38,0x3f,0x40};

u16 NUM=432;
u8 bai,shi,ge,aa,bb,cc,t,times,flag,flag1;

void delay(u16 x)
{
        u16 y,z;
         for(y=0;y<x;y++)
                for(z=0;z<115;z++);
}

void smg_display()
{
        u8 i;
        if(flag1==1)
        {
                  cc=10;bb=11;aa=12;bai=13;shi=14;ge=15;
        }
        else
        {
                 cc=7;bb=6;aa=5;
        }
         for(i=0;i<6;i++)
        {
                 switch(i)
                {
                         case(0):LSA=0;LSB=0;LSC=0;SMG_A_DP_PORT=gsmg_code[ge];delay(1);break;
                        case(1):LSA=1;LSB=0;LSC=0;SMG_A_DP_PORT=gsmg_code[shi];delay(1);break;
                        case(2):LSA=0;LSB=1;LSC=0;SMG_A_DP_PORT=gsmg_code[bai];delay(1);break;
                        case(3):LSA=1;LSB=1;LSC=0;SMG_A_DP_PORT=gsmg_code[aa];delay(1);break;
                        case(4):LSA=0;LSB=0;LSC=1;SMG_A_DP_PORT=gsmg_code[bb];delay(1);break;
                        case(5):LSA=1;LSB=0;LSC=1;SMG_A_DP_PORT=gsmg_code[cc];delay(1);break;
                }
                P0=0x00;
        }
}

void timer0_init()
{
         TMOD=0x01;
        TH0=(65535-50000)/256;
        TL0=(65535-50000)%256;
        EA=1;
        ET0=1;
        TR0=1;
}

void timer1_init()
{
         TMOD=0x10;
        TH1=(65535-50000)/256;
        TL1=(65535-50000)%256;
        EA=1;
        ET1=1;
        TR1=1;
}

void main()
{
        timer0_init();
         timer1_init();

        while(1)
        {
                 smg_display();
        }
}

void timer0() interrupt 1
{
        u8 i,u;
         TH0=(65535-50000)/256;
        TL0=(65535-50000)%256;
        t++;
        if(flag!=1)//控制LED流水灯
        {
                if(t==74)//要定时0.5秒,可是正确的数字无法达到...
                {
                         t=0;
                        if(i<8)
                        {
                                 LED_PORT=_crol_(0xfe,i);
                                i++;
                        }
                        if(i>7)
                        {
                                 LED_PORT=_cror_(0x7f,u);
                                u++;
                        }
                        if(u==7)
                        {
                                i=0;
                                u=0;
                        }
                }
        }
        else//控制LED闪烁
        {
                 if(t%20==0)
                {
                         LED_PORT=0x00;
                        delay(500);
                        LED_PORT=0xff;
                }
                if(t==60)
                {
                         TR0=0;//关闭定时器0
                        LED_PORT=0xff;
                        flag1=1;//控制显示字母
                }
        }         
}

void timer1() interrupt 3
{
         TH1=(65535-50000)/256;
        TL1=(65535-50000)%256;
        times++;
        if(times==2)
        {
                times=0;
                 NUM--;
                bai=NUM/100;
                shi=NUM/100/10;
                ge=NUM%10;
        }
        if(NUM==398)//NUM=398时,流水灯停止
        {
                 TR0=0;
                LED_PORT=0xff;
                TH0=(65535-50000)/256;
                TL0=(65535-50000)%256;
                t=0;
                TR0=1;//再次打开定时器0
                flag=1;//定时器0 else条件成立,LED闪烁
                TR1=0;//关闭定时器1保持字母数据显示
        }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:68189 发表于 2022-12-15 22:08 | 只看该作者
请问你是根据所使用的晶振来计算定时器时间的吗?
回复

使用道具 举报

板凳
ID:213173 发表于 2022-12-16 07:20 | 只看该作者
定时器精度误差是由晶振频率误差和代码编写合理共同确定的。楼主选用的晶振频率与代码是否相适应不得而知,但开两个相同定时时间的中断肯定是不当的,并且还在T1中断中操作T0。
回复

使用道具 举报

地板
ID:161164 发表于 2022-12-16 07:56 | 只看该作者
因为你的TMOD用了"="来设定
定时器1的设定覆盖了定时器0
令定时器0变为13位定时器
回复

使用道具 举报

5#
ID:879348 发表于 2022-12-16 08:05 | 只看该作者
新手常犯毛病,老手都是用&|操作来修改寄存器
回复

使用道具 举报

6#
ID:45879 发表于 2022-12-16 09:24 | 只看该作者
wufa1986 发表于 2022-12-16 08:05
新手常犯毛病,老手都是用&|操作来修改寄存器

一语中的
回复

使用道具 举报

7#
ID:71233 发表于 2022-12-16 10:43 | 只看该作者
中断程序尽量不要运行太多太复杂的代码。
回复

使用道具 举报

8#
ID:213173 发表于 2022-12-16 12:36 | 只看该作者
地板指出的错误是其定时时间超快的主要问题!
回复

使用道具 举报

9#
ID:1044091 发表于 2022-12-16 16:45 | 只看该作者
第一,设置定时器的代码尽量从STC-ISP(定时器计算器)里复制,不容易出错;

第二,中断函数里执行代码不能太多了。我前两天也遇到了类似问题,代码放在中断函数里运行速度超慢,后来移到main()里,只在中断函数里放时间标志位,就正常了。
回复

使用道具 举报

10#
ID:1034262 发表于 2022-12-16 21:41 | 只看该作者
如果定时器使用自动重装,则中断一定会准确(精度与主频一致),问题是你的程序要及时响应。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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