新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 89S51單片機(jī)實(shí)現(xiàn)誤差幾微秒的計(jì)時(shí)程序

89S51單片機(jī)實(shí)現(xiàn)誤差幾微秒的計(jì)時(shí)程序

作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
小弟學(xué)習(xí)單片機(jī)時(shí)間很短,這樣的文章對(duì)于熟悉的人說很是菜,,不過我的目的不是顯擺我多NB,其實(shí)我根本就是個(gè)菜鳥,我的目的只是想通過這篇文章給和我一樣的初級(jí)學(xué)者有一定幫助,至少我把這個(gè)程序?qū)懗鰜砗?,自己?duì)單片機(jī)的一些概念的理解確實(shí)有幫助,好了進(jìn)入正題!

我們都知道單片機(jī)是工作在脈沖之下,而晶振這個(gè)電子元件就是核心,所以單片機(jī)里的計(jì)時(shí)計(jì)數(shù)器都是通過晶振的脈沖數(shù)量來計(jì)算的,晶振的規(guī)格主要就就是它的振蕩頻率,有12MHZ,11.0592MHZ,8MHZ等等,我們知道,機(jī)器周期就是通過 12 * 晶振的頻率的倒數(shù) 得到的,比如使用12MHZ的單片機(jī)它的機(jī)器周期就是1微秒,也就是執(zhí)行一個(gè)單指令周期需要的時(shí)間。說到這里很多初學(xué)者會(huì)有個(gè)和我開始一樣的疑問,就是為什么要搞個(gè)1.0592MHZ的晶振呢?用整數(shù)不好么?我開始也是摸不著頭腦,但是當(dāng)我學(xué)習(xí)到串口通訊的時(shí)候,就恍然大悟了,具體為什么這里就不介紹了,不明白的可以去了解下串口通訊,相信你也會(huì)恍然大悟。
我的實(shí)驗(yàn)板上用的是89S51芯片,使用的晶振是8MHZ的,所以我的89S51執(zhí)行一個(gè)單周期指令就需要12* 1/8 = 1.5微秒,好了有了這個(gè)就可以開始了:
首先我們用匯編寫一個(gè)延遲程序,該程序有三個(gè)參數(shù),分別為x,y,z,用的是三個(gè)循環(huán)鑲套的結(jié)構(gòu),至于為什么不用2個(gè),,很簡(jiǎn)單,因?yàn)槲覀円x值的寄存器是8位的,所以范圍只能是256,如果用2層那么最大只能是256*256=65536,而我們的一秒鐘可是1000000微秒,所以顯然不夠,用三層我們就可以得到最大256*256*256=16777216,這樣才夠用,好了分析下面的這個(gè)延時(shí)程序到底延遲多久:

本文引用地址:http://butianyuan.cn/article/201611/318295.htm

我們的目的就是要使得這個(gè)延遲盡量達(dá)到1000000微秒的時(shí)間,所以x,y,z的值還不確定,先不管,先分析下每一行執(zhí)行的時(shí)間,說明一下,這里的mov是單周期指令,執(zhí)行一次就是1.5微秒(別問我怎么來的,前面算的),而djnz是個(gè)雙周期指令,執(zhí)行一次就是1.5*2=3微秒,知道這個(gè)了就看下面程序每行后面的具體計(jì)算時(shí)間

YS_1S: mov r0,#x 1.5 (只執(zhí)行了一次,所以1.5微秒)
d1: mov r1,#y 1.5*x (執(zhí)行了x次,每次1.5微秒)
d2: mov r2,#z 1.5*x*y 同上
d3: djnz r2,d3 2*1.5*x*y*z (雙周期指令所以還要乘2)
djnz r1,d2 2*1.5*x*y 同上
djnz r0,d1 2*x 同上
ret 1.5

現(xiàn)在我們把每行相加,1.5 + 1.5*x + 1.5*x*y + 2*1.5*x*y*z + 2*1.5*x*y + 2*x + 1.5得到這個(gè)公式,現(xiàn)在要求這個(gè)公式算出來大概等于 1000000, 我們把這個(gè)公式加以簡(jiǎn)化,就的到如下方程:


3+4.5*x+4.5*x*y+3*x*y*z = 1000000


現(xiàn)在我們要求x,y,z的值,怎么求呢?隨便用自己熟悉的語言,用窮舉法,我是用C++寫的,如下:

int x,y,z;

for(x=1;x<=256;x++)
for(y=1;y<=256;y++)
for(z=1;z<=256;z++)
//這里我沒寫1000000是因?yàn)楹苡锌赡軙?huì)出現(xiàn)這個(gè)方程不會(huì)完全等于1000000,所以我還是取了個(gè) 范圍,所以為什么題目說是幾微秒的誤差了,
if(((999990>=(3+4.5*x+4.5*x*y+3*x*y*z)))&&((1000000<=(3+4.5*x+4.5*x*y+3*x*y*z))))
{
cout < }

最后我得到的是x=205 y=171 z=8;這三個(gè)參數(shù)放到公式里算出來是999993,所以這個(gè)延遲就誤差7微秒,把這三個(gè)值放到開始的延遲程序?qū)?yīng)的xyz里,燒寫到89S51里,隨便用個(gè)發(fā)光2極管做閃爍,就可以看到效果了,再用秒表做一個(gè)粗造的測(cè)試,就OK了。
其實(shí),我這個(gè)方法很笨,但我的目的是學(xué)習(xí),而且自己的學(xué)習(xí)有點(diǎn)小小的成果后,拿出來和別人分享,哪怕是錯(cuò)誤的,至少我知道錯(cuò)誤在哪里,改正錯(cuò)誤,這又是一種進(jìn)步。



評(píng)論


技術(shù)專區(qū)

關(guān)閉