矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 5762|回复: 12

关于90C516RD+定时问题

[复制链接]
     
发表于 2013-1-23 18:50:21 | |阅读模式
关于90C516RD+定时问题
自己准备用90C516单片机做个可调时钟的,按理论上来说,时钟定时器的工作方式2,12M晶振,定时器益处时间为200微妙,然后循环5000次,到达定时1S的目的,但是实际确是运行的速度缓慢,就是定时时间太长了,最终将循环次数减少到108次才勉强可以,不知道高手能不能指点一下~~先谢过了
     
发表于 2013-1-23 18:59:26 |
本帖最后由 longshort 于 2013-1-23 19:00 编辑

注意对计数器设置的数值应当是补数,而且还应该减去进入中断所花的周期和中断返回所花的周期,以及中断服务程序中其它指令的总周期。
一般来说,响应中断大约要花3~7个工作周期,中断返回是两个周期,108个循环周期中这两个就要占用324~756个工作周期和216个工作周期,每个工作周期1uS,则至少要占用540~972uS。
     
 楼主| 发表于 2013-1-23 19:02:44 |
longshort 发表于 2013-1-23 18:59
注意对计数器设置的数值应当是补数,而且还应该减去进入中断所花的周期和中断返回所花的周期,以及中断服务 ...

我使用的是查询模式,而且是工作方式2,所以误差不会吗么大吧
     
发表于 2013-1-23 19:12:57 |
静夜思月晖 发表于 2013-1-23 19:02
我使用的是查询模式,而且是工作方式2,所以误差不会吗么大吧

计数器哪能用查询方式读值?这样读出来的值是不准确的。
你得用计数器自动重装方式带中断,再用一个寄存器做辅助计数器,每来一次中断,辅助计数器减一,到减为零时就是你要的时间长度了。
     
 楼主| 发表于 2013-1-23 20:03:13 |
longshort 发表于 2013-1-23 19:12
计数器哪能用查询方式读值?这样读出来的值是不准确的。
你得用计数器自动重装方式带中断,再用一个寄存 ...

我使用的是定时模式,使用查询方式的,这样应该可以吧,而且我说的误差是由5000变到110.差的太多了
     
发表于 2013-1-24 00:21:23 |
200微秒的中断频率太高了,1秒内中断调转的时间误差就会更大了
     
发表于 2013-1-28 11:13:41 |
把程序贴上来大家才好帮你分析啊!
     
发表于 2013-1-28 11:31:07 |
本帖最后由 翌阳 于 2013-1-28 11:37 编辑

用中断方式,自动装载方式定时器,计时精度很高的。注意如果有其它中断,要保证此中断最高优先,且不能被屏蔽。中断处理程序尽量短。定时器时间尽量长,以能计算出整秒为好。我DIY的那个2051时钟就是这么做的,TH=TL=0自装载,咋取整呢,选合适频率的晶体啊。

具体参考一下这里: http://www.crystalradio.cn/thread-163673-1-1.html
     
 楼主| 发表于 2013-1-28 16:24:49 |
翌阳 发表于 2013-1-28 11:31
用中断方式,自动装载方式定时器,计时精度很高的。注意如果有其它中断,要保证此中断最高优先,且不能被屏 ...

谢谢建议,我使用的就是自动重装初值的模式2,而且使用查询方式,没有其他中断,下面是程序源码,使用12.00M晶振,你方便的话,麻烦帮我分析下,谢了
#include<reg52.h>
#define  uchar unsigned char
#define  uint unsigned int
sbit set=P3^2;
sbit add=P3^3;
sbit dec=P3^4;
int shi,fen,miao;
void xianshi(int weizhi,int shuzhi);
void xianshi1(int c);
void delay(x);
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code weizhi[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
void delay(x)
{
        int i;                                                                                                  
        while(x--)
        for(i=0;i<110;i++);
}
main()
{        int i,flag=0;
        EA=0;
        ET0=0;
        TMOD=0X02;
        TH0=0X38;
        TL0=0X38;
        TR0=1;
        while(1)
        {
        if(TF0==1)
        {
                i++;
                TF0=0;
                if(i==110)
                {
                        i=0;
                        miao++;
                        if(miao==60)
                        {
                                miao=0;
                                fen++;
                                if(fen==60)
                                {
                                        fen=0;
                                        shi++;
                                        if(shi==24)                                                          
                                        {
                                                shi=0;
                                        }
                                }
                        }
                }
        }
                if(set==0)
                {
                        delay(10);
                        if(set==0)
                        {
                                TR0=0;
                                flag=1;
                                while(~set);
                        }
                }
                                while(flag==1)
                                {
                                        xianshi(7,miao);
                                        xianshi(4,fen);
                                        xianshi(1,shi);
                                        xianshi1(2);
                                        xianshi1(5);
                                        if(set==0)
                                        {
                                                delay(10);
                                                if(set==0)
                                                {
                                                        flag=2;
                                                //TR0=1;
                                                 }
                                                 while(~set);
                                        }
                                if(add==0)
                                {
                                        delay(10);
                                        if(add==0)
                                        {
                                                shi++;
                                                if(shi==24)
                                                {
                                                        shi=0;
                                                }
                                                while(~add);
                                        }
                                }
                                        if(dec==0)
                                        {
                                                delay(10);
                                                if(dec==0)
                                                {
                                                        fen++;
                                                       
                                                        if(fen==60)
                                                        {
                                                                fen=0;

                                                        }
                                                }
                                                while(~dec);
                                        }
                                       
                                }
                                if(flag==2)
                                {
                                        flag=0;
                                        TR0=1;
                                }
                //TR0=1;
                xianshi(7,miao);
                xianshi(4,fen);
                xianshi(1,shi);
                //xianshi1(2);
                //xianshi1(5);
        }
}

void xianshi(int c,int shuzhi)
{
        int a,b;
        a=shuzhi/10;
        b=shuzhi%10;
        P2=weizhi[c];
        c--;
        P0=table;
        delay(1);
        P0=0xff;
        P2=weizhi[c];
        P0=table[a];
        delay(1);
}

void xianshi1(int c)
{
        P2=weizhi[c];
        P0=0x40;
}

void dingshi() interrupt 1
{
        TH0=0X38;
        TL0=0X38;
}
     
发表于 2013-1-28 16:32:02 |
本帖最后由 翌阳 于 2013-1-28 16:33 编辑

void dingshi() interrupt 1
{
        TH0=0X38;
        TL0=0X38;
}
你这中断里是做啥的?这样精度差。这不是自装载,自装载在中断里不给定时寄存器的赋值,这工作是由硬件自动完成的。中断里只计数。
类似这样写:
void timer0(void) interrupt 1
{
    timcnt--;
    if(timcnt==0)
    {
        if(!modi)sec++;     
        if(sec>119)sec=0;
        dot=!dot;
        timcnt=TIMCNT;
    }
}
     
 楼主| 发表于 2013-1-28 16:40:50 |
翌阳 发表于 2013-1-28 16:32
void dingshi() interrupt 1
{
        TH0=0X38;

这个地方的中断函数可以不写的,我是在主函数里面进行计数值的累加的#include<reg52.h>

main()
{        int i,flag=0;
        EA=0;
        ET0=0;
        TMOD=0X02;
        TH0=0X38;
        TL0=0X38;
        TR0=1;
        while(1)
        {
        if(TF0==1)
        {
                i++;
                TF0=0;
                if(i==110)
                {
                        i=0;
                        miao++;
                        if(miao==60)
                        {
                                miao=0;
                                fen++;
                                if(fen==60)
                                {
                                        fen=0;
                                        shi++;
                                        if(shi==24)                                                          
                                        {
                                                shi=0;
                                        }
                                }
                        }
                }
        }
        并且没有关闭定时器,您看看,可以吗
     
发表于 2013-1-28 18:06:40 |
可以。缺点是MCU比较忙,而且不可以做太长时间的事,否则执行过长时间的程序,比如延时之类的或者扫描就会把丢个计数。
在中断里计数,计到秒就可以了。一般来说查询很少会连1秒时间都漏掉。
     
 楼主| 发表于 2013-1-28 18:33:35 |
翌阳 发表于 2013-1-28 18:06
可以。缺点是MCU比较忙,而且不可以做太长时间的事,否则执行过长时间的程序,比如延时之类的或者扫描就会把 ...

O ,非常感谢啊,我再试试————————————————————

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-5-19 11:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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