烦恼的威尔逊 2023-11-25 15:59 采纳率: 0%
浏览 12
已结题

51单片机内部计时器制作时钟如何把误差缩小到一天5s以内

使用的51开发板为普中的开发板 晶振11.0592
主代码如下:


#include <REGX52.H>
#include <INTRINS.H>
#include "Delay.h"
#include "Nixie.h"
#include "LCD1602.h"
#include "MatrixKey.h"
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
unsigned int DATE[6]={2023,11,8,0,0,0};
unsigned int CMode,EMode;
static unsigned int T0count;
int KeyNumber;
int DATESlect = 5;


unsigned int Month_BOS(unsigned int Month)
{
    if(Month !=2 && Month%7%2==1 || Month%7==0)
        return 1;
    else if(Month !=2 && Month%7%2==0 && Month%7!=0)
        return 0;
    else if(Month == 2)
        return 2;


}
unsigned int is_leap_year(int j)
{
    if (((j % 4 == 0) && (j % 100!= 0)) || (j % 400 == 0))
        return 1;//是闰年
    else
        return 0;//不是闰年
 
}
void TADD()
{
    if(DATE[5]>=60)
        {
            DATE[5]=0;
            DATE[4]++;
            }
    if(DATE[4]>=60)
        {
            DATE[4]=0;
            DATE[3]++;
          }
    if(DATE[3]>=24)
        {
            DATE[3]=0;
            DATE[2]++;
            }
    if((Month_BOS(DATE[1])==1&&DATE[2]==32)||(Month_BOS(DATE[1])==0&&DATE[2]==31)||(Month_BOS(DATE[1])==2&&DATE[2]==30&&is_leap_year(DATE[0]))||(Month_BOS(DATE[1])==2&&DATE[2]==29&&!is_leap_year(DATE[0])))
        {
            DATE[2] =1;
            DATE[1]++;
         }
    if(DATE[1]>12)
        {
            DATE[1]=1;
            DATE[0]++;
            }
}
void main()
{    
    LCD_Init();
    Time_Init();
    LCD_ShowString(1,1,"Clock:");
    
    while(1)
    {
        KeyNumber=Key();
        if(KeyNumber)
        {
            if(KeyNumber==1)
            {
                CMode+=1;
                if(CMode>=2)CMode=0;
            }
            if(KeyNumber==2)
            {
                EMode+=1;
                if(EMode>=2)EMode=0;
            }
        
        }
        if(CMode==0)
        {
            LCD_ShowNum(2,1,DATE[3],2);
            LCD_ShowString(2,3,":");
            LCD_ShowNum(2,4,DATE[4],2);
            LCD_ShowString(2,6,":");
            LCD_ShowNum(2,7,DATE[5],2);
            LCD_ShowString(2,9,"  ");
        
        }
        if(CMode==1)
        {
            LCD_ShowNum(2,1,DATE[0],4);
            LCD_ShowString(2,5,"-");
            LCD_ShowNum(2,6,DATE[1],2);
            LCD_ShowString(2,8,"-");
            LCD_ShowNum(2,9,DATE[2],2);
        
        
        }
        if(EMode==1)
        {
            if(KeyNumber)
            {
            
                if(KeyNumber==3)
                {
                
                    DATESlect-=1;
                    if(DATESlect<0)DATESlect=5;
                
                }
                if(KeyNumber==4)
                {
                    DATE[DATESlect]++;
                    TADD();
              }
            }
        }
        if(EMode==0)
      {
            if(T0count>=5000)
          {
            T0count=0;
            DATE[5]++;
            TADD();
        }
      }
    }
    
}
    


void Timer0_Routine() interrupt 1
{
    T0count++;
    }

计时器代码如下

#include <REGX52.H>
void Time_Init()    
{
    TMOD = 0x02;        //设置定时器模式
    TL0 = 72;        //设置定时初值
    TH0 = 72;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //660开始计时
    ET0 = 1;
    EA = 1;
    PT0 = 0;
}

思路是计时器模式2计时200us5000个循环增加1s 但是误差很高 麻烦在不改变大体框架的基础上帮我把误差减小到1天5s以内 谢谢

  • 写回答

18条回答 默认 最新

  • bug菌¹ Java领域优质创作者 2023-11-25 22:46
    关注
    获得0.75元问题酬金

    该回答引用ChatGPT,望对题主有所帮助/启发;若有帮助,还望采纳。


    你的计时器误差可能来自于晶振频率的不确定性,以及51单片机定时器的工作方式。为了减小误差,你可以考虑以下几点:

    1. 晶振频率校准: 你在代码中使用的是11.0592MHz的晶振,但实际晶振的频率可能略有偏差。你可以通过一些精密的设备来测量实际晶振频率,然后将这个值用于计算。

    2. 精确的定时器设置: 你的计时器设置为定时器模式2,每次计数需要 200 微秒,总共 5000 次循环为 1 秒。确保 TL0 和 TH0 的初值准确,使得定时器的计时精度更高。

    3. 考虑中断延迟: 在中断服务程序中,可能存在一些延迟,这可能导致计时误差。你可以尽量简化中断服务程序,减小中断延迟。

    4. 校正误差: 你可以在运行时通过外部手段(比如通过网络获取标准时间)来校正单片机内部的时间。每隔一段时间进行一次校正,可以使系统的时间更加准确。

    5. 考虑定时器的精度: 51单片机的定时器精度受限,你可以考虑使用更高性能的单片机或者外部实时时钟模块来提高计时的精度。

    在你的代码中,你可以通过以下方式来调整:

    TL0 = 60;   // 重新设置定时初值
    TH0 = 60;   // 重新设置定时初值
    

    这样可以使得每个定时器周期略微减小,从而减小误差。此外,你也可以通过调整晶振频率的偏差来进一步校准。

    评论

报告相同问题?

问题事件

  • 系统已结题 12月3日
  • 创建了问题 11月25日

悬赏问题

  • ¥15 如何构建全国统一的物流管理平台?
  • ¥100 ijkplayer使用AndroidStudio/CMake编译,如何支持 rtsp 直播流?
  • ¥20 和学习数据的传参方式,选择正确的传参方式有关
  • ¥15 这是网络安全里面的poem code
  • ¥15 用js遍历数据并对非空元素添加css样式
  • ¥15 使用autodl云训练,希望有直接运行的代码(关键词-数据集)
  • ¥50 python写segy数据出错
  • ¥20 关于线性结构的问题:希望能从头到尾完整地帮我改一下,困扰我很久了
  • ¥30 3D多模态医疗数据集-视觉问答
  • ¥20 设计一个二极管稳压值检测电路