久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6487|回復: 16
收起左側

51單片機做數字鐘 定時器中斷有誤差 如何提高精度

[復制鏈接]
ID:516644 發表于 2020-5-18 18:59 | 顯示全部樓層 |閱讀模式
20黑幣
    使用51單片機做一個簡單的數字鐘,但是用定時器中斷時,進入中斷服務函數時會有機器周期,會產生誤差。    怎么減少這種誤差?或者如果用補償的方式增加定時器的初值,應該怎么計算需要補償的數值?
    以下部分代碼是我使用補償修正值的方式,但是修正值不正確。

u8 fixtime; //定義修正變量

void time0_init(void)
{
        TMOD |= 0X01;  //選擇為定時器0模式,工作方式1,僅用TR0打開啟動。

        TH0 = 0XD8;           //給定時器賦初值,定時10ms
        TL0 = 0XF0;       
        ET0 = 1;       //打開定時器0中斷允許
        EA = 1;        //打開總中斷
        TR0 = 1;       //打開定時器                       
}

void Timer0() interrupt 1
{
        EA = 0;//禁止所有中斷請求
        TR0 = 0;//關閉T0
        fixtime = TL0 + 0X1B;//將TL0中已計數值寫入fixtime,并加上修正操作占用的27個機器周期
        TL0 = 0XF0 + fixtime;//將修正值寫入TL0
        TH0 = 0XD8 + (char)CY;//修正TL0時可能產生進位,要補償到TH0
        EA = 1;//允許所有中斷請求
        TR0 = 1;//開啟TR0
        msec++;
        if(msec == 100)          //1sec = 1000ms
        {
                msec = 0;
                sec++;
        }
        if(sec == 60)            //1min = 60sec
        {
                sec = 0;
                min++;
        }
        if(min == 60)            //1hour = 60min
        {
                min = 0;
                hour++;
        }
}


最佳答案

查看完整內容

仿真受PC時鐘影響,不一定準,要用實物驗證。仿真用不了STC89C52的EEPROM保存fixtime變量。給你基本補齊了。
回復

使用道具 舉報

ID:213173 發表于 2020-5-18 18:59 | 顯示全部樓層
LOVEqing 發表于 2020-5-20 18:47
#include
#include "lcd.h"
#define uint unsigned int

仿真受PC時鐘影響,不一定準,要用實物驗證。仿真用不了STC89C52的EEPROM保存fixtime變量。給你基本補齊了。

無標題.jpg


無標題1.jpg

  1. //適用STC89C52RC單片機
  2. #include <reg52.h>
  3. #include <intrins.h>
  4. #define uint unsigned int
  5. #define uchar unsigned char

  6. //定義ISP的操作命令
  7. #define RdCommand 0x01                //讀命令
  8. #define PrgCommand 0x02                //寫命令
  9. #define EraseCommand 0x03        //擦除命令
  10. #define Error 1
  11. #define Ok 0
  12. #define WaitTime 0x01                 //定義CPU的等待時間,寫入硬件延時
  13. //STC89系列EEPROM寄存器聲明
  14. sfr ISP_DATA=0xe2;                //0000,0000 EEPROM數據寄存器
  15. sfr ISP_ADDRH=0xe3;                //0000,0000 EEPROM地址高字節
  16. sfr ISP_ADDRL=0xe4;                //0000,0000 EEPROM地址第字節
  17. sfr ISP_CMD=0xe5;                //xxxx,xx00 EEPROM命令寄存器
  18. sfr ISP_TRIG=0xe6;                //0000,0000 EEPRPM命令觸發寄存器
  19. sfr ISP_CONTR=0xe7;                //0000,x000 EEPROM控制寄存器

  20. sbit key0=P3^3;
  21. sbit key1=P3^4;
  22. sbit key2=P3^5;
  23. sbit rs=P2^6;         //寄存器選擇信號 H:數據寄存器          L:指令寄存器
  24. sbit rw=P2^5;         //寄存器選擇信號 H:數據寄存器          L:指令寄存器
  25. sbit e =P2^7;         //片選信號   下降沿觸發
  26. uchar sec=0,min=0,hour=12;
  27. uchar num=0;
  28. uint  usec=0;
  29. //uint  fixtime=10000; //定義修正變量
  30. uint  fixtime;        //定義修正變量
  31. bit   sec_flag=0;    //秒標志

  32. // 打開 ISP,IAP 功能
  33. void ISP_IAP_enable(void)
  34. {
  35.         EA = 0;       /* 關中斷   */
  36.         ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  37.         ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
  38.         ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
  39. }
  40. // 關閉 ISP,IAP 功能
  41. void ISP_IAP_disable(void)
  42. {
  43.         ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  44.         ISP_TRIG = 0x00;
  45.         EA   =   1;   /* 開中斷 */
  46. }
  47. // 公用的觸發代碼
  48. void ISPgoon(void)
  49. {
  50.         ISP_IAP_enable();   /* 打開 ISP,IAP 功能 */
  51.         ISP_TRIG = 0x46;  /* 觸發ISP_IAP命令字節1 */
  52.         ISP_TRIG = 0xb9;  /* 觸發ISP_IAP命令字節2 */
  53.         _nop_();
  54. }
  55. // 字節讀
  56. unsigned char byte_read(unsigned int byte_addr)
  57. {
  58.         ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
  59.         ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  60.         ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  61.         ISP_CMD   = ISP_CMD | RdCommand; /* 寫入讀命令 */
  62.         ISPgoon();       /* 觸發執行  */
  63.         ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  64.         return (ISP_DATA);    /* 返回讀到的數據 */
  65. }
  66. // 扇區擦除
  67. void SectorErase(unsigned int sector_addr)
  68. {
  69.         unsigned int iSectorAddr;
  70.         iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
  71.         ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  72.         ISP_ADDRL = 0x00;
  73.         ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  74.         ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
  75.         ISPgoon();       /* 觸發執行  */
  76.         ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  77. }
  78. // 字節寫
  79. void byte_write(unsigned int byte_addr, unsigned char original_data)
  80. {
  81.         ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  82.         ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  83.         ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  84.         ISP_CMD  = ISP_CMD | PrgCommand;  /* 寫命令2 */
  85.         ISP_DATA = original_data;   /* 寫入數據準備 */
  86.         ISPgoon();       /* 觸發執行  */
  87.         ISP_IAP_disable();     /* 關閉IAP功能 */
  88. }
  89. /********************************************************************
  90. * 名稱 : delay_uint()
  91. * 功能 : 小延時。
  92. * 輸入 : 無
  93. * 輸出 : 無
  94. ***********************************************************************/
  95. void delay_uint(uint i)
  96. {
  97.         while(--i);
  98. }

  99. /********************************************************************
  100. * 名稱 : write_com(uchar com)
  101. * 功能 : 1602命令函數
  102. * 輸入 : 輸入的命令值
  103. * 輸出 : 無
  104. ***********************************************************************/
  105. void write_com(uchar com)
  106. {
  107.         e=0;
  108.         rs=0;
  109.         rw=0;
  110.         P0=com;
  111.         delay_uint(25);
  112.         e=1;
  113.         delay_uint(25);
  114.         e=0;
  115. }

  116. /********************************************************************
  117. * 名稱 : write_data(uchar dat)
  118. * 功能 : 1602寫數據函數
  119. * 輸入 : 需要寫入1602的數據
  120. * 輸出 : 無
  121. ***********************************************************************/
  122. void write_data(uchar dat)
  123. {
  124.         e=0;
  125.         rs=1;
  126.         rw=0;
  127.         P0=dat;
  128.         delay_uint(25);
  129.         e=1;
  130.         delay_uint(25);
  131.         e=0;       
  132. }
  133. /***********************lcd1602初始化設置************************/
  134. void init_1602()
  135. {
  136.         write_com(0x38);       
  137.         write_com(0x0c);
  138.         write_com(0x06);
  139.         write_com(0x01);
  140. }
  141. void time0_init(void)
  142. {
  143.     TMOD = 0x02;//自動重裝
  144.     TH0 = 0x9C; //100us
  145.     TL0 = 0x9C;
  146.     EA = 1;
  147.     ET0 = 1;
  148.     TR0 = 1;
  149. }

  150. void LCD1602_init(void)
  151. {
  152.         uchar i;
  153.         uchar a[]=" Digital Clock  ";
  154.         write_com(0x80);
  155.         for(i=0;i<16;i++)
  156.                 write_data(a[i]);
  157. }

  158. void display(void)
  159. {
  160.         write_com(0xc0+13);
  161.         if(num==0)
  162.                 write_data(' ');
  163.         else if(num==1)
  164.                 write_data('H');
  165.         else if(num==2)
  166.                 write_data('M');
  167.         else if(num==3)
  168.                 write_data('S');
  169.         write_com(0x80+0x44);
  170.         if(num==4)
  171.         {
  172.                 write_data('F');
  173.                 write_data('=');
  174.                 write_data('=');
  175.                 write_data(fixtime/10000%10+'0');
  176.                 write_data(fixtime/1000%10+'0');
  177.                 write_data(fixtime/100%10+'0');
  178.                 write_data(fixtime/10%10+'0');
  179.                 write_data(fixtime%10+'0');
  180.                 write_data(' ');
  181.                 write_data(' ');
  182.         }
  183.         else
  184.         {
  185.                 write_data(hour/10+'0');
  186.                 write_data(hour%10+'0');
  187.                 write_data(':');
  188.                 write_data(min/10+'0');
  189.                 write_data(min%10+'0');
  190.                 write_data(':');
  191.                 write_data(sec/10+'0');
  192.                 write_data(sec%10+'0');
  193.         }
  194. }

  195. void keyscan()
  196. {
  197.         static bit key_lock=0;        //按鍵自鎖標志
  198.         static uchar count=0;        //消抖計數變量               
  199.         uchar i=0,a,b;
  200.         if(!key0||!key1||!key2)
  201.         {
  202.                 if(++count>=10 && key_lock==0)
  203.                 {
  204.                         key_lock=1;//自鎖
  205.                         if(!key0)
  206.                         {
  207.                                 num++;
  208.                                 num%=5;
  209.                         }
  210.                         if(!key1 && num>0)
  211.                         {
  212.                                 switch(num)
  213.                                 {
  214.                                         case 1: hour++;if(hour>=24)hour=0; break;
  215.                                         case 2: min++; if(min>=60) min=0;  break;
  216.                                         case 3: sec++; if(sec>=60) sec=0;  break;
  217.                                         case 4: fixtime++;
  218.                                                         a=fixtime>>8;
  219.                                                         b=fixtime;
  220.                                                         SectorErase(0x2000);//擦除扇區
  221.                                                         byte_write(0x2000,a);//重新寫入數據高8位
  222.                                                         byte_write(0x2001,b);//重新寫入數據低8位
  223.                                                         break;
  224.                                         default:  break;
  225.                                 }
  226.                         }
  227.                         if(!key2 && num>0)
  228.                         {
  229.                                 switch(num)
  230.                                 {
  231.                                         case 1: hour--;if(hour>=24)hour=23; break;
  232.                                         case 2: min--; if(min>=60) min=59;  break;
  233.                                         case 3: sec--; if(sec>=60) sec=59;  break;
  234.                                         case 4: fixtime--;
  235.                                                         a=fixtime>>8;
  236.                                                         b=fixtime;
  237.                                                         SectorErase(0x2000);//擦除扇區
  238.                                                         byte_write(0x2000,a);//重新寫入數據高8位
  239.                                                         byte_write(0x2001,b);//重新寫入數據低8位
  240.                                                         break;
  241.                                         default:  break;
  242.                                 }
  243.                         }
  244.                 }
  245.         }
  246.         else   //松手
  247.         {
  248.                 count=0;
  249.                 key_lock=0;
  250.         }
  251. }

  252. void Timing()//計時程序
  253. {
  254.         if(sec_flag)
  255.         {
  256.                 sec_flag=0;
  257.                 sec++;
  258.                 if(sec >= 60)
  259.                 {
  260.                         sec = 0;
  261.                         min++;
  262.                         if(min >= 60)
  263.                         {
  264.                                 min = 0;
  265.                                 hour++;
  266.                                 if(hour >= 24)
  267.                                         hour=0;
  268.                         }
  269.                 }
  270.         }
  271. }

  272. void main()
  273. {
  274.         init_1602();
  275.         LCD1602_init();
  276.         fixtime=byte_read(0x2000);//程序開始時讀取EEPROM中數據
  277.         fixtime=fixtime<<8|byte_read(0x2001);//合并為整形數據
  278.         if(fixtime>15000||fixtime<5000) //防止首次上電時讀取出錯
  279.                 fixtime=10000;
  280.         time0_init();
  281.         while(1)
  282.         {
  283.                 keyscan();
  284.                 Timing();
  285.                 display();
  286.         }
  287. }

  288. void Timer0() interrupt 1
  289. {
  290.         if(++usec>=fixtime)  //1sec
  291.         {
  292.                 usec = 0;
  293.                 sec_flag=1;
  294.         }
  295. }
復制代碼



STC99封裝.zip

26.37 KB, 下載次數: 7

回復

使用道具 舉報

ID:584814 發表于 2020-5-19 11:08 | 顯示全部樓層
如果僅用單片機內部時鐘,除調整晶振頻率等硬件外,軟件通過調整定時器的初值,計算值加實驗修正。
想獲得精準時鐘,直接外部時鐘便宜且方便。
回復

使用道具 舉報

ID:267719 發表于 2020-5-19 11:34 | 顯示全部樓層
用方式2,自動重載模式。定時到比如100us。這樣就只有相鄰誤差,沒有累計誤差。
晶振匹配不同的電容,實際的頻率也是有誤差的。這個補償要累計去計算的,比如1個月后,誤差多少個ms,平均每天或每小時差多少個ms(這個值小于1000),到整天或整小時的時候調整(根據實際情況去加或減。加好辦,注意減的處理)。
僅提供一種思路做參考。。
回復

使用道具 舉報

ID:213173 發表于 2020-5-19 16:35 | 顯示全部樓層
給你一個程序框架,自己補充完整。可以做到日誤差<10秒
  1. #include <reg51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. sbit key1=P3^4;
  5. sbit key2=P3^5;

  6. uchar sec,min,hour;
  7. uint  usec=0;
  8. uint  fixtime=10000; //定義修正變量
  9. bit   sec_flag=0;                //秒標志

  10. void time0_init(void)
  11. {
  12.     TMOD = 0x02;//自動重裝
  13.     TH0 = 0x9C; //100us
  14.     TL0 = 0x9C;
  15.     EA = 1;
  16.     ET0 = 1;
  17.     TR0 = 1;
  18. }

  19. void keyscan()
  20. {
  21.         static bit key_lock=0;        //按鍵自鎖標志
  22.         static uchar count=0;        //消抖計數變量               
  23.         if(!key1||!key2)
  24.         {
  25.                 if(++count>=100 && key_lock==0)
  26.                 {
  27.                         key_lock=1;//自鎖
  28.                         if(!key1)
  29.                                 fixtime++;
  30.                         if(!key2)
  31.                                 fixtime--;
  32.                 }
  33.         }
  34.         else   //松手
  35.         {
  36.                 count=0;
  37.                 key_lock=0;
  38.         }
  39.         //其它調時語句
  40. }

  41. void display()//顯示程序
  42. {
  43.         //顯示
  44. }

  45. void Timing()//計時程序
  46. {
  47.         if(sec_flag)
  48.         {
  49.                 sec_flag=0;
  50.                 sec++;
  51.                 if(sec >= 60)
  52.                 {
  53.                         sec = 0;
  54.                         min++;
  55.                         if(min >= 60)
  56.                         {
  57.                                 min = 0;
  58.                                 hour++;
  59.                                 if(hour >= 24)
  60.                                         hour=0;
  61.                         }
  62.                 }
  63.         }
  64. }

  65. void main()
  66. {
  67.         time0_init();
  68.         while(1)
  69.         {
  70.                 keyscan();
  71.                 Timing();
  72.                 display();
  73.         }
  74. }

  75. void Timer0() interrupt 1
  76. {
  77.         if(++usec>=fixtime)  //1sec
  78.         {
  79.                 usec = 0;
  80.                 sec_flag=1;
  81.         }
  82. }
復制代碼
回復

使用道具 舉報

ID:516644 發表于 2020-5-19 17:44 | 顯示全部樓層
carpcarey 發表于 2020-5-19 11:34
用方式2,自動重載模式。定時到比如100us。這樣就只有相鄰誤差,沒有累計誤差。
晶振匹配不同的電容,實際 ...

為什么我修改成方式2之后,1602顯示的數值都不會變了。只修改了定時器的配置。定時時間是100us
回復

使用道具 舉報

ID:732506 發表于 2020-5-19 20:42 | 顯示全部樓層
讓鐘運行較長一段時間,比如10-20小時,看誤差萬分之多少,根據誤差調整fixtime的值。一次可能不行,多試幾次,應該能不斷減小誤差。調整到每天誤差幾十秒應該是可以的,要進一步提高比較困難,因為使用按鍵時會對程序的執行時間有影響。
回復

使用道具 舉報

ID:267719 發表于 2020-5-20 09:09 | 顯示全部樓層
LOVEqing 發表于 2020-5-19 17:44
為什么我修改成方式2之后,1602顯示的數值都不會變了。只修改了定時器的配置。定時時間是100us

看看代碼
回復

使用道具 舉報

ID:516644 發表于 2020-5-20 16:51 | 顯示全部樓層

#include "reg52.h"
#include "lcd.h"

#define u8 unsigned char
#define u16 unsigned int
       
u8 init[] = "0123456789";
u8 msec;       //毫秒
u8 sec;        //秒
u8 min;        //分
u8 hour;       //時

void LCD1602_init(void)
{
        LcdWriteCom(0x01);
        LcdWriteData(' ');
        LcdWriteData('D');
        LcdWriteData('i');
        LcdWriteData('g');
        LcdWriteData('i');
        LcdWriteData('t');
        LcdWriteData('a');
        LcdWriteData('l');
        LcdWriteData(' ');
        LcdWriteData(' ');
        LcdWriteData('C');
        LcdWriteData('l');
        LcdWriteData('o');
        LcdWriteData('c');
        LcdWriteData('k');
        LcdWriteData(' ');
}

void LCD1602_show(void)
{
        LcdWriteCom(0x80 + 0x40);
        LcdWriteData(init[hour / 10]);
        LcdWriteData(init[hour % 10]);
        LcdWriteData(':');
        LcdWriteData(init[min / 10]);
        LcdWriteData(init[min % 10]);
        LcdWriteData(':');
        LcdWriteData(init[sec / 10]);
        LcdWriteData(init[sec % 10]);
}
void time0_init(void)
{
        TMOD = 0X02;  //選擇為定時器0模式,工作方式2,僅用TR0打開啟動。

        TH0 = 0X9C;           //給定時器賦初值,定時0.1ms
        TL0 = 0X9C;       
        ET0 = 1;       //打開定時器0中斷允許
        EA = 1;        //打開總中斷
        TR0 = 1;       //打開定時器
}

void main(void)
{
                LcdInit();
                time0_init();
                LCD1602_init();
                while(1)
                {
                                LCD1602_show();
                }
}

void Timer0(void) interrupt 1
{
        msec++;
        if(msec == 10000)          //1sec = 1000ms
        {
                msec = 0;
                sec++;
        }
        if(sec == 60)            //1min = 60sec
        {
                sec = 0;
                min++;
        }
        if(min == 60)            //1hour = 60min
        {
                min = 0;
                hour++;
        }
        if(hour == 24)
                        hour = 0;
}

大概是這樣
回復

使用道具 舉報

ID:548551 發表于 2020-5-20 17:03 | 顯示全部樓層
wulin 發表于 2020-5-19 16:35
給你一個程序框架,自己補充完整。可以做到日誤差

請問老哥.51單片機都不初始化IO口嗎? 還有就是晶振頻率,以及上下拉打開不打開. 還有看門狗也不初始化??
回復

使用道具 舉報

ID:73435 發表于 2020-5-20 17:03 | 顯示全部樓層
中斷里面處理盡可能快,所以你的很多代碼可以放到中斷外,中斷里面就是一個簡單的累加就好了。
回復

使用道具 舉報

ID:267719 發表于 2020-5-20 17:21 | 顯示全部樓層
LOVEqing 發表于 2020-5-20 16:51
#include "reg52.h"
#include "lcd.h"

u8 msc  不對 u16 msc因為后面 if (msec == 10000)          //1sec = 1000ms
如果u8 msc,始終不會等于10000的,最大只能255.
回復

使用道具 舉報

ID:516644 發表于 2020-5-20 18:47 | 顯示全部樓層
wulin 發表于 2020-5-19 16:35
給你一個程序框架,自己補充完整。可以做到日誤差

#include <reg52.h>
#include "lcd.h"
#define uint unsigned int
#define uchar unsigned char

uchar init[] = "0123456789";

sbit key1=P3^4;
sbit key2=P3^5;

uchar sec,min,hour;
uint  usec=0;
uint  fixtime=10000; //定義修正變量
bit   sec_flag=0;                //秒標志

void time0_init(void)
{
    TMOD = 0x02;//自動重裝
    TH0 = 0x9C; //100us
    TL0 = 0x9C;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void LCD1602_init(void)
{
        LcdWriteCom(0x01);
        LcdWriteData(' ');
        LcdWriteData('D');
        LcdWriteData('i');
        LcdWriteData('g');
        LcdWriteData('i');
        LcdWriteData('t');
        LcdWriteData('a');
        LcdWriteData('l');
        LcdWriteData(' ');
        LcdWriteData(' ');
        LcdWriteData('C');
        LcdWriteData('l');
        LcdWriteData('o');
        LcdWriteData('c');
        LcdWriteData('k');
        LcdWriteData(' ');
}

void LCD1602_show(void)
{
        LcdWriteCom(0x80 + 0x40);
        LcdWriteData(init[hour / 10]);
        LcdWriteData(init[hour % 10]);
        LcdWriteData(':');
        LcdWriteData(init[min / 10]);
        LcdWriteData(init[min % 10]);
        LcdWriteData(':');
        LcdWriteData(init[sec / 10]);
        LcdWriteData(init[sec % 10]);
}

void keyscan()
{
        static bit key_lock=0;        //按鍵自鎖標志
        static uchar count=0;        //消抖計數變量               
        if(!key1||!key2)
        {
                if(++count>=100 && key_lock==0)
                {
                        key_lock=1;//自鎖
                        if(!key1)
                                fixtime++;
                        if(!key2)
                                fixtime--;
                }
        }
        else   //松手
        {
                count=0;
                key_lock=0;
        }
        //其它調時語句
}

void display()//顯示程序
{
      LCD1602_show();  //顯示
}

void Timing()//計時程序
{
        if(sec_flag)
        {
                sec_flag=0;
                sec++;
                if(sec >= 60)
                {
                        sec = 0;
                        min++;
                        if(min >= 60)
                        {
                                min = 0;
                                hour++;
                                if(hour >= 24)
                                        hour=0;
                        }
                }
        }
}

void main()
{
        time0_init();
        LcdInit();
        LCD1602_init();

        while(1)
        {
                keyscan();
                Timing();
                display();
        }
}

void Timer0() interrupt 1
{
        if(++usec>=fixtime)  //1sec
        {
                usec = 0;
                sec_flag=1;
        }
}

我就增加了1602顯示,用protues仿真,然后誤差還是蠻大的,大概1602顯示25s的時候 手機秒表已經跑到28了
回復

使用道具 舉報

ID:516644 發表于 2020-5-21 10:11 | 顯示全部樓層
carpcarey 發表于 2020-5-20 17:21
u8 msc  不對 u16 msc因為后面 if (msec == 10000)          //1sec = 1000ms
如果u8 msc,始終不會等于 ...

哦哦哦 是的呢,忘記了
回復

使用道具 舉報

ID:516644 發表于 2020-5-21 19:00 | 顯示全部樓層
wulin 發表于 2020-5-21 12:09
仿真受PC時鐘影響,不一定準,要用實物驗證。仿真用不了STC89C52的EEPROM保存fixtime變量。給你基本補齊 ...

哈哈哈哈哈,有道理,主要是手頭沒有開發板,沒法實物測試。你這都把鐘基本做出來了
回復

使用道具 舉報

ID:57657 發表于 2023-3-8 14:52 | 顯示全部樓層
高精度必須自動重載初值,定時器0中斷內不能向TH0和TL0寄存器賦值,有多個中斷注意優先級問題。
回復

使用道具 舉報

ID:1034262 發表于 2023-3-8 17:10 | 顯示全部樓層
定時器工作于自動重裝模式,本身不會造成誤差。
我用一個有源恒溫晶振,北斗模塊校準過,作為單片機(STC8H4K64TL)的時鐘,定時器工作于16位自動重裝模式,1年的誤差不超過0.3秒。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲成人免费视频在线 | 嫩草黄色影院 | 久久免费精品 | 美女亚洲一区 | 精品国产伦一区二区三区观看方式 | 欧美黑人激情 | 久久亚洲国产 | 天天av天天好逼 | 欧美精品一区二区三区在线播放 | 日本久久久久久久久 | 欧美影院 | 成年人黄色小视频 | 日操夜操 | 成人在线精品视频 | 亚洲一区二区三区久久久 | 成人免费视频一区二区 | 国产欧美一区二区在线观看 | 午夜精品久久久久久久星辰影院 | 在线视频一区二区 | 亚洲在线成人 | 亚洲一区三区在线观看 | 欧美久久久久久 | 日韩电影免费在线观看中文字幕 | 中文字幕av在线 | 日韩欧美成人精品 | 奇米影视在线 | 欧美色人 | 日韩中文字幕 | 国产精品国产自产拍高清 | 天天拍天天色 | 国产精品特级毛片一区二区三区 | 美女久久视频 | 日韩精品一区二区三区中文在线 | 美女久久 | 久久99精品久久久久子伦 | 亚洲精品一区在线观看 | 91高清免费观看 | 欧美视频 亚洲视频 | 免费在线黄色av | 久久激情视频 | 欧美亚洲国产一区 |