定時器的難點也就在這裡了。我們使用定時器時,通過手冊可以查詢到T0定時器是有4中工作方式的,每種工作方式是不一樣的,也就導致了設置的方法也稍有不同。先看下手冊中的四種方式。
先不管如何設置的,我們先看下這四種模式,第一種是13位定時器,從學習到實踐,這麼久,我還沒有用過這種模式,想使用的可以試試,個人覺得也許就是為了兼容以前的設備,沒有其他左右,也許有,我不知道。
第二種是16位定時器模式,就是說,可以完成一個十六位二進位數的加法,從0000000000000000加到1111111111111111,看著就覺得很大的數,轉成十進位就是0-65535。
第三種是8位自動重裝定時器。先用低八位計時,計時結束,再把高八位數據放到低八位中繼續計時。
第四種是兩個8位定時器。
看到這裡,是不是有個疑問?計時器不是計時的嗎?怎麼沒有看到定時的參數?不都是像秒表一樣一秒一秒的走的嗎?這裡需要我們詳細的解釋下,定時器是如何定時的。
在單片機中,有這麼一個裝置,之前我們就看到過,還有同學說我仿真中為何不畫出來,那就使晶振。晶振的作用就是單片機的心跳,沒有它,單片機就失去了走下去的動力。可以說單片機的程序運行就是踩著晶振的頻率一步一步走下去的,晶振越穩定,單片機就越精確。
晶振又是如何影響單片機的運行呢?這要說到一個東西——晶振頻率。之前的實驗中,總是會說到我使用的晶振頻率是11.0592MHz,這裡的11.0592MHz就是晶振的頻率,是晶振發出的時鐘信號,十分精確。就相當於一個人在分秒不差的一秒喊一聲「到」,這個晶振就是趴在那裡一秒喊了11059200次「到」而且間隔十分一致。於是單片機就以這個頻率來確定自己的運行時間,常規的單片機的機器周期是晶振頻率的1/12,就是說,運行一次最簡單的代碼,需要震動12次,那麼一秒鐘可以完成的機器周期數是11059200/12=921600次這是頻率,通過頻率可以計算出一次的時間是T=1/f=1/921600=1.08507^-6秒,換算成微秒就是1.08507微秒,也就是程序完成一次運算的最短時間是1.08507微秒。
然後我們就可以用這個來作為基礎時間,單片機的最基礎運算是加減運算,都是佔用一個機器周期,我們的定時器就是靠著加法來完成定時的。例如我們前文所說的第二種定時器使用方式中,16位定時器,就是讓一個0一直加到65535,這個加的過程是單片機自己完成的,無需我們控制。如果從0開始到65535,我們可以計算出所消耗的時間是:1.08507*65535=71110.06245微秒,也就是71.110毫秒。當定時器加到65536時,就會溢出,然後清零,並觸發中斷。
這個溢出又是一個新詞。溢出的意思是滿了,裝不下了。我們假設一個3位定時器。最初是000,隨著不斷的加一,一直加到了111,當程序再加一時,由於只有三位數,再加一就該進位了,進位之後,進上去的1沒地方放,就扔了,餘下了三個0。這個扔掉的1就是溢出,像是水盆水滿了,再倒水就溢出去了。當定時器溢出後,會有一個專門的標誌位,去監控這個溢出現象,一但溢出,這個標誌位就會變成1,於是我們就可以通過這個溢出標誌位,來查看定時器是不是加到頭了。
由於加到頭的時間有整有零,不是很好算,所以往往會選擇一個整數時間來定時。方法就是不讓定時器從頭開始加,我給他一個其實值,讓他從起始值往後加,這樣時間就變得短了,通過控制起始值,就可以控制定時時間了。
比如0-65535是71110.06245微秒,假設我想讓他50000微秒完成一次計時。那麼就可以通過50000除以一次的時間,得出計時50000微秒需要的次數。
50000/1.08507=46079.97641次,程序中不存在半次的周期,所以需要使用整數,就是約46080次,有了這一次的四捨五入,就造成了計時的誤差。每50毫秒就多用了0.02359次,相當於每50毫秒長了1.08507*0.02359=0.0255968013微秒,一秒鐘就是20個50毫秒,一分鐘就是1200個50毫秒,一小時就是72000個50毫秒,就相當於單片機一小時時間比真正的一小時長了0.0255968013*72000=1842.969694微秒。一個小時誤差2毫秒,是不是相當精確了。
有些同學看著這些個數就頭疼,也怪我,就好使用這個11.0592MHz的晶振。但是方法有了,用什麼晶振都是可以的,無非就是計算一下數據而已。
當計算出46080時,就相當於知道了單片機只需要查夠46080個數就可以完成一次計時50毫秒任務了。那麼初始值就不再是0了,最大值是無法改變的,我們只有改變最小值,讓它不從0開始。要想查夠46080剛好到65536,這就需要用65536減去46080得到19456,也就是定時器要從19456開始計數。
這個19456需要存儲到一個地方,好讓每次計數完後可以找到他,然後繼續計數。在中斷中有這麼一個配置,就是兩個8位的存儲空間,分別是高八位TH0,低八位TL0。我們要把這個初始值19456轉換成二進位,然後拆成兩個八位二進位。
使用科學計數器19456=0b1001 1000 0000 0000=0x98 00,高八位就是0x98,低八位就是0x00。
至此定時器的定時設置就算完成了。
這是我們在使用方式1的情況下的定時器數值。TH0=0x80,TL0=0x00。
如果是為了方便,可以採用12MHz的晶振。
我們來計算下,一個周期的時間就是:
f=1200000/12=1000000次。
T=1/f=1/1000000=1微秒。整數,是不是看起來好多了。那麼從0加到65535就是65.535毫秒,我們需要50毫秒,就是需要50000次,口算就可以得到。比那個11.0592MHz簡單很多是吧。後邊的計算時差不多的,65536-50000=15536。然後把15536計算成二進位就可以了。
15536=0b0011 1100 1011 0000=0x3C B0。TH0=0x3C,TL0=0xB0。
好吧,就是這麼簡單。
設置時間步驟:
1,查看晶振頻率。
2,計算出一個機器周期的時間,大部分是12分之一,也有些是6分之一的,注意查看手冊。
3,設置定時器一個中斷周期時間長度。
4,計算出累加一個時間長度所需累加數,然後計算出初始值。
5,使用科學計算器,計算出初始值的二進位數,把二進位數分為兩個八位數。把二進位轉換為十六進位。
6,把高八位十六進位寫入TH0,低八位十六進位寫入TL0。
通過這六個步驟,就算是完成了時間設置。假設是一個12M的晶振。
1,頻率12M。
2,機器周期時間是1/(12M/12)=1微秒。
3,假設需要定時50毫秒。
4,累加數,50000/1=50000。65536-50000=15536。初始值15536。
5,15536=0b0011 1100 1011 0000=0x3C B0。不夠十六位的,在二進位數前補0,湊夠十六位。
6,TH0=0x3C,TL0=0xB0。