找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 9423|回復(fù): 20
收起左側(cè)

關(guān)于用51單片機(jī)做時(shí)鐘顯示準(zhǔn)確度的問(wèn)題

  [復(fù)制鏈接]
ID:301968 發(fā)表于 2018-7-28 11:35 | 顯示全部樓層 |閱讀模式
一直看到好多人說(shuō),用單片機(jī)做時(shí)間顯示不準(zhǔn)確.
其實(shí)我認(rèn)為用單片機(jī)做時(shí)間顯示,可以達(dá)到非常 精確的地步,比如三天誤差小于1S.不知大家認(rèn)為這種誤差是大還是小.
當(dāng)然要用外部晶體嘍.
用定時(shí)器1MS中斷,計(jì)算1000MS,累進(jìn)一秒.
以互聯(lián)網(wǎng)北京時(shí)間實(shí)時(shí)時(shí)間比對(duì).
先測(cè)試24小時(shí)誤差,一般初次會(huì)誤差較大,幾秒到十秒都有可能.誤差大了,就先修改定時(shí)值.
誤差小了,我們就用另外一種方法來(lái)消除誤差.
比如,10小時(shí),誤差慢1秒鐘,36000秒,慢一秒,就是36000MS慢1MS
定時(shí)器,1000MS,計(jì)時(shí)36次時(shí),將MS計(jì)時(shí)數(shù)強(qiáng)行加1,依此原理.
如3天慢一秒,259200秒,慢1秒.
在定時(shí)器中斷函數(shù)中
計(jì)算259次累進(jìn)一秒時(shí),MS強(qiáng)行加1
利用這種方式,可以做出非常精確的時(shí)間顯示功能
謝謝大家,有好的方法,請(qǐng)分享給大家,互相學(xué)習(xí)!!!



評(píng)分

參與人數(shù) 1黑幣 +80 收起 理由
admin + 80 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:357194 發(fā)表于 2018-7-28 19:56 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:380012 發(fā)表于 2018-7-28 21:24 | 顯示全部樓層
晶振會(huì)產(chǎn)生溫漂,軟件上的初嘗只能解決特定環(huán)境下的時(shí)鐘精度,不能解決所有的環(huán)境。
回復(fù)

使用道具 舉報(bào)

ID:111634 發(fā)表于 2018-7-29 16:44 | 顯示全部樓層
單片機(jī)用定時(shí)器產(chǎn)生秒基準(zhǔn)做的時(shí)鐘不精確,必須用外部時(shí)鐘芯片。
回復(fù)

使用道具 舉報(bào)

ID:619208 發(fā)表于 2019-10-4 13:52 | 顯示全部樓層
我為啥一分鐘差了十多秒#include<reg51.h>
#include "DS1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED3 = P0^2;
uint count=0;
uint counter=0;
uint b=0;
uchar i=0;
uchar code table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};         //共陰極段碼。
/*void Time1_Init()
{
        TMOD = 0x60;
        TL1 = 0xFE;
        TH1 = 0xFE;
        ET1 = 1;
        EA=1;
        TR1=1;
}  */

void Time1_Int() interrupt 3  //計(jì)數(shù)器的中斷。
{
          counter++;          //記錄脈沖數(shù)。
}
void Time0_Init()           //定時(shí)計(jì)數(shù)器的初始化
{
        TMOD = 0x61;   //T1計(jì)數(shù)器工作方式2(自動(dòng)重裝初值),T0計(jì)時(shí)器工作方式1。
        TH0 = 0xD8;           //T0初值為55536,計(jì)時(shí)10ms。
        TL0 = 0xF0;
        TL1 = 0xFF;           //T1初值為FF,記錄脈搏脈沖,每次都中斷。
        TH1 = 0xFF;
        ET0 = 1;           //開啟T0中斷使能;
        ET1 = 1;           //開啟T1中斷使能;
        EA = 1;                   //總中斷是能開關(guān)開啟;
        TR0 = 1;           //T0開始計(jì)時(shí);
        TR1=1;                   //T1可以開始計(jì)數(shù);
}
void Time0_Int() interrupt 1          //定時(shí)器的中斷。
{
        TH0=0xD8;                //重裝初值。
        TL0=0xF0;
        count++;                //記錄10ms個(gè)數(shù);
}
void DelayMS(uchar x)                //普通延時(shí);
{
        while(x--)
        {
                uint i;
                for(i=0;i<10;i++)
                {
                        ;
                }
        }
}
void Int0_Int() interrupt 0                 //外部中斷0中斷程序:初始化定時(shí)計(jì)數(shù)器0、1;
{               
        b++;                                                 //b自加
        if(b==1)                                         //如果b等于1,說(shuō)明按鈕只按了一次,開始測(cè)試。
                 Time0_Init();                         //初始化T0,T1,開始計(jì)時(shí)計(jì)數(shù)。
        if(b>1)                                                 //如果b>1,說(shuō)明一次測(cè)試已完成第二次按下按鈕,重新測(cè)試。
        {
                counter=0;                                 //清零示數(shù)。
                i=0;
                Time0_Init();                         //初始化T0,T1,開始計(jì)時(shí)計(jì)數(shù)。
        }
}
void main()                         //主程序
{         
        //uchar i=0;
        //Time0_Init();                  //初始化定時(shí)計(jì)數(shù)器;
        //Time1_Init();
        EA = 1;                                  //中斷總使能開關(guān)開
        EX0 = 1;                          //外部中斷0是能開關(guān)開
        while(1)                          //循環(huán);
        {
                if(count==100)          //如果10ms個(gè)數(shù)為100個(gè),即經(jīng)過(guò)1s時(shí),i自加一,count清零;
                {
                        i++;
                        count=0;
                }
        /*        P2=table[i % 10];
                P1=0x02;*/
                        P2=table[i % 10];        //P2輸出顯示i秒的個(gè)位數(shù);
                        P1=table[counter % 10];
                        LED1=0;                                //P0^0點(diǎn)位低電平;
                        DelayMS(1);                        //延時(shí)一會(huì);
                        LED1=1;                                //P0^0電位高電平
                        P2=table[(i / 10)%10];                                //輸出顯示i秒的十位;
                        P1=table[(counter / 10)%10];
                        LED2=0;                                //P0^1電位低電平;
                        DelayMS(1);                        //延時(shí)一會(huì);
                        LED2=1;
                        P1=table[(counter/100)%10];
                        LED3=0;
                        DelayMS(1);
                        LED3 = 1;
                                                 //P0^1電位高電平;
                if(i==60)                                //當(dāng)i達(dá)到60秒時(shí),停止中斷使能,計(jì)數(shù)和計(jì)時(shí)停止;
                {
                        ET0=0;
                        ET1=0;                               
                }
               
        }

}
回復(fù)

使用道具 舉報(bào)

ID:67199 發(fā)表于 2019-10-4 19:46 | 顯示全部樓層
imanoob 發(fā)表于 2019-10-4 13:52
我為啥一分鐘差了十多秒#include
#include "DS1302.h"
#define uchar unsigned char

先調(diào)整重裝初值  TH0=0xD8;   TL0=0xF0;   再根據(jù)實(shí)測(cè)誤差,加上修正值。  
        
回復(fù)

使用道具 舉報(bào)

ID:491577 發(fā)表于 2019-10-5 23:41 | 顯示全部樓層
時(shí)鐘精準(zhǔn)度只是與計(jì)時(shí)用的晶振的精度有關(guān),與時(shí)鐘芯片無(wú)關(guān),同樣一個(gè)晶振,不管用什么時(shí)鐘芯片或者用單片機(jī)都是一樣的精度,高精度鐘芯片都是自帶晶振的而且?guī)в袦囟妊a(bǔ)償,所以精度高,如果單片機(jī)使用高精度晶振并且檢測(cè)晶振的溫度做溫度補(bǔ)償,一樣可以做到很高的精度。樓主還缺一個(gè)溫度檢測(cè),要標(biāo)定晶振在不同的溫度下的偏差,在程序中做補(bǔ)償還可以提高精度。沒(méi)有溫度補(bǔ)償,夏天和冬天誤差不一樣的。
回復(fù)

使用道具 舉報(bào)

ID:612180 發(fā)表于 2019-10-7 14:39 | 顯示全部樓層
其實(shí)51單片機(jī)的內(nèi)部電路會(huì)對(duì)時(shí)鐘電路有一定的影響,而晶振的頻率也會(huì)有影響,所以要做時(shí)間顯示的話可以用STM32單片機(jī),更精確一點(diǎn)。
回復(fù)

使用道具 舉報(bào)

ID:158375 發(fā)表于 2019-10-7 15:08 | 顯示全部樓層
樓主想的有點(diǎn)簡(jiǎn)單嘍,實(shí)際過(guò)程要復(fù)雜多多.
回復(fù)

使用道具 舉報(bào)

ID:620317 發(fā)表于 2019-10-8 10:20 | 顯示全部樓層
如果想要更準(zhǔn)確的時(shí)間,建議用時(shí)鐘芯片。比如microchip的MCP7940,Resolution 1 ppm.
回復(fù)

使用道具 舉報(bào)

ID:301968 發(fā)表于 2021-6-12 13:52 | 顯示全部樓層
我用了一個(gè)幾毛錢的片子做了一個(gè)鬧鐘,幾個(gè)月都沒(méi)調(diào)時(shí)間,誤差也沒(méi)過(guò)1分鐘。
回復(fù)

使用道具 舉報(bào)

ID:47286 發(fā)表于 2021-6-12 14:30 | 顯示全部樓層
時(shí)鐘這東西 說(shuō)白了就是對(duì)精度要求有多高 如果1年允許誤差1個(gè)月 什么方法都沒(méi)問(wèn)題 要求1年差1s還得以內(nèi) 我覺(jué)得 你的方法沒(méi)戲

以下是我對(duì)時(shí)間模塊的理解而已 今天放假 多寫了點(diǎn) 有喜歡的就看看 不喜歡掠過(guò)即可

我認(rèn)為時(shí)鐘準(zhǔn)確不準(zhǔn)確主要是時(shí)鐘源的問(wèn)題 和用什么做關(guān)系不是特別大 綜合精度 消耗精力 成本三者評(píng)比

GPS最好 精度高 消耗精力小 成本高

GPS時(shí)鐘源精度和世界鐘精度一樣 但GPS經(jīng)過(guò)的節(jié)點(diǎn)少 衛(wèi)星的時(shí)鐘完全不是普通設(shè)備可以比的 那東西要給軍用提供授時(shí) GPS接收模塊可以提供1ms級(jí)別的通訊授時(shí) 高手可以根據(jù)收到的時(shí)間 每次提前若干ms開始處理 這樣若干年下來(lái)也不會(huì)有誤差 除非斷電了 而且電波傳輸速度接近光速 節(jié)點(diǎn)就是衛(wèi)星到模塊 中間經(jīng)過(guò)的節(jié)點(diǎn)少 物理延遲很小

網(wǎng)絡(luò)授時(shí) 精度較高 消耗精力小 成本高

網(wǎng)絡(luò)授時(shí)是從世界鐘或者叫RTC服務(wù)器發(fā)出的數(shù)據(jù)包獲得時(shí)間 理論上也很準(zhǔn) 問(wèn)題是 你并不是用一根網(wǎng)線直接連到RTC服務(wù)器上 以太網(wǎng)的結(jié)構(gòu)全球有無(wú)數(shù)個(gè)節(jié)點(diǎn) 一個(gè)時(shí)間數(shù)據(jù)別說(shuō)全球 僅國(guó)內(nèi)就要經(jīng)過(guò)若干個(gè)網(wǎng)關(guān) 而TCP/IP協(xié)議的效率是很低的 一個(gè)數(shù)據(jù)包有7層 包括各種數(shù)據(jù) 而且以太網(wǎng)是分時(shí)復(fù)用傳輸數(shù)據(jù) 并不是連貫的 每一個(gè)網(wǎng)關(guān) 直到本地接收后 都要重新打包 解包 還原數(shù)據(jù) 所以延遲比GPS要大 GPS需要專用模塊 以太網(wǎng)獲取時(shí)間也需要 成本上并沒(méi)多大區(qū)別

單片機(jī)+芯片 精度一般 消耗精力多 成本較低

這個(gè)方法就是片子讀片子 精度問(wèn)題由時(shí)鐘芯片控制 好芯片 好調(diào)試 精度還行 到不了1s/年以下 考慮到要獲得較高京精度 需要從軟件或者硬件做誤差補(bǔ)償 消耗精力比較多 成本方面 如果用好片子 成本嘛 呵呵 也不比上面兩種方式低 用便宜片子嘛 那就多花精力唄

純單片機(jī) 精度不好說(shuō) 消耗精力大 成本低

這個(gè)方案的精度實(shí)在不好控制 精度最高的應(yīng)該算用有源晶振吧 那也得晶振夠好 有源晶振又怎么了 一樣有優(yōu)劣區(qū)別 無(wú)源晶振次之 一樣受溫度影響 內(nèi)部RC更是受溫度變化影響 這種變化讓人頭疼的是沒(méi)準(zhǔn) 不一定差多少 通常能用的方法都是觀察累積誤差然后想辦法補(bǔ)償 但這種補(bǔ)償說(shuō)白了都是開環(huán)的 一切補(bǔ)償都基于觀察規(guī)律 并沒(méi)有實(shí)時(shí)反饋的閉環(huán)修正 環(huán)境變化大也沒(méi)多大用 成本肯定是最低的 反正只要有振蕩源 也不過(guò)就是個(gè)片子 不需要其它東西

回復(fù)

使用道具 舉報(bào)

ID:883242 發(fā)表于 2021-6-12 17:00 | 顯示全部樓層
想準(zhǔn)用TCXO好了。OCXO太費(fèi)電。
回復(fù)

使用道具 舉報(bào)

ID:517951 發(fā)表于 2021-6-12 19:29 | 顯示全部樓層
用DS12887和51單片機(jī)搭配,精度可以做到一年1分鐘以內(nèi)的誤差,51單片機(jī)IO8bit4個(gè)對(duì)應(yīng)12887的8bit8080接口還有富裕。你們有興趣可以是試試。
回復(fù)

使用道具 舉報(bào)

ID:301968 發(fā)表于 2021-6-17 16:41 | 顯示全部樓層
用DS12887和單片機(jī)搭配,可能用的最多,精度這個(gè)問(wèn)題嘛,看場(chǎng)合嘍。十天半個(gè)月差個(gè)幾S一般問(wèn)題不大呵。生活中使用嘛,一般差個(gè)一兩分鐘我們都不會(huì)介意。
回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2021-6-18 13:30 | 顯示全部樓層
用單片機(jī)本身的晶振作為時(shí)鐘,那肯定是不怎么的
容易產(chǎn)生誤差,而且是差異化的,你所寫的程序只能在這個(gè)晶振上有用,換一個(gè)晶振就不一定行了
對(duì)于單片機(jī)晶振的要求太高了,掉電還不能保存
時(shí)鐘芯片估計(jì)是每個(gè)學(xué)單片機(jī)的人都會(huì)接觸到的,但時(shí)鐘芯片也有不同各類的,像DS1302這種外置晶振的,只適合批量生產(chǎn),畢竟它才幾毛錢一片,但調(diào)試設(shè)備卻是幾千塊的.......
DS12887或者DS3231內(nèi)置晶振是最好的選擇
當(dāng)然,編程能力高一點(diǎn)的,WIFI授時(shí)是最有性價(jià)比也是一勞永逸的
我做過(guò)一個(gè)大鐘放老家,有一次打雷就復(fù)位了,結(jié)果老人在家不會(huì)調(diào),竟然就那樣放了一整年
回復(fù)

使用道具 舉報(bào)

ID:97350 發(fā)表于 2021-6-18 14:28 | 顯示全部樓層
反正我覺(jué)得DS1302是最差勁的,畢竟價(jià)格低廉。
回復(fù)

使用道具 舉報(bào)

ID:272119 發(fā)表于 2021-6-18 14:48 | 顯示全部樓層
最近在做定時(shí)上傳數(shù)據(jù)到上位機(jī),每秒一次,用的是STC15W內(nèi)置IRC還沒(méi)有微調(diào)傳輸幾分鐘就多發(fā)一次數(shù)據(jù). 下載燒錄就知道用IRC設(shè)置時(shí)就會(huì)有偏差.因?yàn)樾酒O(shè)置22.1184Mhz都無(wú)法準(zhǔn)確總會(huì)有個(gè)千分之幾的誤差.
回復(fù)

使用道具 舉報(bào)

ID:344848 發(fā)表于 2024-4-26 09:52 | 顯示全部樓層
單片機(jī)時(shí)鐘顯示的準(zhǔn)確度,建議采用時(shí)鐘芯片。
回復(fù)

使用道具 舉報(bào)

ID:619259 發(fā)表于 2024-4-26 11:25 | 顯示全部樓層
用單片機(jī)定時(shí)器做時(shí)鐘,兩點(diǎn)建議:
1.定時(shí)器使用方式2(8位自動(dòng)重裝);
2.初始值取100微秒,計(jì)數(shù)10000次為1秒,若時(shí)間有誤差,可微調(diào)這個(gè)計(jì)數(shù)值。
回復(fù)

使用道具 舉報(bào)

ID:883242 發(fā)表于 2024-4-26 19:51 | 顯示全部樓層
Y_G_G 發(fā)表于 2021-6-18 13:30
用單片機(jī)本身的晶振作為時(shí)鐘,那肯定是不怎么的
容易產(chǎn)生誤差,而且是差異化的,你所寫的程序只能在這個(gè)晶振 ...

說(shuō)反了,單片機(jī)接的AT-cut晶體穩(wěn)定性遠(yuǎn)遠(yuǎn)優(yōu)于RTC用的fork crystal,只是耗電量大,不適合掉電運(yùn)行。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表