新聞中心

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

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

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

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

本文引用地址:http://2s4d.com/article/201611/318295.htm

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

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得到這個公式,現(xiàn)在要求這個公式算出來大概等于 1000000, 我們把這個公式加以簡化,就的到如下方程:


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是因為很有可能會出現(xiàn)這個方程不會完全等于1000000,所以我還是取了個 范圍,所以為什么題目說是幾微秒的誤差了,
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;這三個參數(shù)放到公式里算出來是999993,所以這個延遲就誤差7微秒,把這三個值放到開始的延遲程序?qū)膞yz里,燒寫到89S51里,隨便用個發(fā)光2極管做閃爍,就可以看到效果了,再用秒表做一個粗造的測試,就OK了。
其實,我這個方法很笨,但我的目的是學習,而且自己的學習有點小小的成果后,拿出來和別人分享,哪怕是錯誤的,至少我知道錯誤在哪里,改正錯誤,這又是一種進步。



評論


技術專區(qū)

關閉