搜索
bottom↓
回复: 10

单片机定时1s慢了许多 请大神帮忙

[复制链接]

出0入0汤圆

发表于 2012-9-8 16:34:55 | 显示全部楼层 |阅读模式
#include<reg52.h>
#include<ye12864.h>
unsigned char t,flag = 2;
void Time_Count0_Init()         //定时器初始化函数
{
        TMOD = 0X01;  //设置定时器工作方式为1
        TH0 = 0X4C;          //定时50ms
        TL0 = 0X00;
        PCON=0X80; //波特率倍频
        TR0 = 1;          
        ET0 = 1;
        EA = 1;
}
void xs(uint dd,i,k)  //结果显示函数,dd 要显示的函数,k显示的列数位置,i显示行数位置
{
   uint temp4,temp5,shu[20];
   char j = 0;
   if(dd<10)
   {
                   w_shuzi(k,i,0);
                w_shuzi(k+1,i,dd);               
   }
   else
   {
        while(dd)
                 {
                        temp4 = dd/10;
                        temp5 = dd%10;
                        shu[j++] = temp5;       
                        dd = temp4;
                 }
                 for(--j;j>=0;j--)
                 {
                        w_shuzi(k++,i,shu[j]);
                 }
        }
}
void calendar()                          //万年历函数
{
        unsigned char yue,ri,shi,fen,miao,temp,i,xq;
        unsigned char dyue[] = {1,3,5,7,8,10,12},xyue[4] = {4,6,9,11};
        unsigned int nian;
        if(flag ==2)
        {
                nian = 2012;
                yue = 12;
                ri = 30;
                shi = 22;
                fen = 58;
                miao = 50;
        }
        if(flag == 1)
        {
                miao++;
                if(yue == 12&&ri == 31&&shi == 23&&fen == 59&&miao == 60)
                {
                        yue = 1;
                        ri = 1;
                        shi = 0;
                        fen = 0;
                        miao = 0;
                        xq++;
                }
                if(miao == 60)
                {
                        fen++;
                        miao = 0;
                }
                if(fen == 60)
                {
                        shi++;
                        fen = 0;
                }
                if(shi == 24)
                {
                        shi = 0;
                        ri++;
                        xq++;
                        if(xq == 7)
                        xq = 0;
                }
                if(ri == 28&&ri == 29&&ri == 30&&ri == 31)         //当日期为28,29,30,30,31才判断月份是否加一
                {
                        for(i = 0;i<7;i++)
                        {
                                if(yue == dyue[i])
                                temp = 2;
                        }
                        for(i = 0;i<4;i++)
                        {
                                if(yue == xyue[i])
                                temp = 1;
                                else
                                temp = 0;
                        }
                }
                if(temp == 2)          //是大月
                        if(ri == 31)
                        yue++;
                if(temp == 1)          //是小月
                        if(ri == 30)
                        yue++;
                if(temp == 0)          //2月
                        if (nian%400 == 0 || (nian%4 == 0 && nian%100 != 0))  //是闰年
                        {
                                if(ri == 29)
                                yue++;
                        }
                        else if(ri == 28)
                                  yue++;
                xs(nian,2,0);
                xs(yue,2,6);
                xs(ri,2,9);
                xs(shi,4,0);
                xs(fen,4,3);
                xs(miao,4,6);
                w_hanzi(8,2,xq+5);
                flag = 0;
        }       
}
void main()
{
         LCD_init();
         LCD_qingpin(0x00);
         delay(10);
         Time_Count0_Init(); //定时器初始化
         w_hanzi(0,0,0);        //显示万年历
         w_hanzi(1,0,1);
         w_hanzi(2,0,2);
         w_hanzi(6,2,3);
         w_hanzi(7,2,4);
         while(1)
         {
                 calendar();       
         }
}
void time_count0() interrupt 1
{
        TF0 = 0;
        TH0 = 0X4C;          //定时50ms
        TL0 = 0X00;
        TR0 = 0;
        if(t == 20)
        {
                t = 0;
                flag = 1;
        }
        t++;
        TR0 = 1;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2012-9-8 16:48:46 | 显示全部楼层
不知道楼主是不是用的是STC单片机,精密一点要使用外部晶振!

出0入0汤圆

发表于 2012-9-8 17:23:20 | 显示全部楼层
应当用自动重装模式
若在中断中重装,这个中断的响应的时刻是不确定的,而且从中断响应到进入中断函数是需要时间的

出0入0汤圆

发表于 2012-9-8 19:09:49 | 显示全部楼层
void time_count0() interrupt 1
{
        TR0 = 0;
        TF0 = 0;
        TH0 = 0X4C;          //定时50ms
        TL0 = 0X00;
        TR0 = 1;
        if(t == 20)
        {
                t = 0;
                flag = 1;
        }
        t++;
}
试试看,进一步可以TL0=0x09(可调整),Keil仿真一下。

出0入0汤圆

发表于 2012-9-8 19:38:10 | 显示全部楼层
拿示波器,卡一下时间,,,慢慢调整,

出0入0汤圆

 楼主| 发表于 2012-9-9 08:50:57 | 显示全部楼层
是用STC单片机 晶振是11.0592Mhz

出0入0汤圆

 楼主| 发表于 2012-9-9 08:58:05 | 显示全部楼层
谢谢各位!的确把t++放在if前面就可以了,不过是什么原因还是不明白!

出0入0汤圆

发表于 2012-9-9 15:42:30 | 显示全部楼层
本帖最后由 chengzepeng 于 2012-9-9 16:06 编辑
  1. void time_count0() interrupt 1
  2. {
  3. //      TF0 = 0;                    // 进入中断会自动清,不需要额外加
  4.         TH0 = 0X4c;               // 定时50ms
  5.         --TL0;                        // 减去定时器填充的时间
  6. //     TR0 = 0;                    // 不要关定时器,否则误差更大
  7.         ++t;                           // 把t放在+后面计算更快
  8.         if(t == 20)
  9.         {
  10.                 t = 0;
  11.                 flag = 1;
  12.         }
  13. //        TR0 = 1;
  14. }
复制代码

出0入8汤圆

发表于 2012-9-9 15:46:20 | 显示全部楼层
做时钟,建议用自动重装模式即模式2!!

出0入0汤圆

 楼主| 发表于 2012-9-9 17:23:47 | 显示全部楼层
好的 谢谢各位

出0入0汤圆

发表于 2012-9-9 18:58:01 | 显示全部楼层
i will give you something much simpler and much more accurate, yet without using an auto-reload timer.


  1. #define F_XTAL                11059200ul                //crystal frequency, in Mhz
  2. #define TMR1s                (F_XTAL / 12)        //1st count, in ticks
  3. #define TMR500ms        (TMR1s / 2)                //500ms delay
  4. #define TMR100ms        (TMR1s / 10)        //100ms delay
  5. #define TMR_PR                TMR1s                        //tmr period

  6. unsigned long tmr_cnt = 0;                //tmr counter

  7. ...
  8. //when you initialize the timer, clear TH0/TL0

  9. //isr
  10. void time_count0() interrupt 1
  11. {
  12.                 tmr_cnt += 0x10000ul;                //increment tmr counter
  13.         if(tmr_cnt >= TMR_PR)                                //desired time has elapsed
  14.         {
  15.                 tmr_cnt -= TMR_PR;                //update timer counter
  16.                 flag = 1;
  17.         }
  18. }

复制代码
F_XTAL defines the crystal you are using. If you change crystal in the future, you just need to update the figure here and recompile.
TMR1s defines how many ticks for 1 second, assuming a 12-cycle mcu. if you use a 1-cycle mcu, replace that 12 with 1
TMR500ms / TMR100ms are some pre-define cycle counts, and you can add your own.
TMR_PR is the desired timer period. here we set it to 1 second. If you use TMR500ms instead of TMR1s here, the clock will set flag every 500ms.

in the isr, we increment tmr_cnt. 0x10000ul for a 16bit timer. if you were to use an 8-bit timer, use 0x100 instead.

no auto reloading. the timer will be as accurate as your crystal, particularly in long-term applications. you can also introduce trimming here to get the timer incredibly accurate.

It is called the Black Roman approach.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 18:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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