這是我總結的51單片機的中斷定時器原理,之后會附上附件。第一次發帖,不足之處請多多包含!
我總結的文稿畫面很花,所以給上個參考,各位不習慣的話,請酌情選擇。
定時器.jpg (25.83 KB, 下載次數: 347)
下載附件
2017-12-26 22:53 上傳
參考.jpg (75.2 KB, 下載次數: 235)
下載附件
2017-12-26 23:12 上傳
目錄 一、原理: 1、對中斷和定時器進行初始化: ①定時器/計數器工作方式寄存器 ②設定初值 ③開啟中斷和定時器 2、設置中斷服務程序: 3、主函數: 二、各個定時器和工作方式: 方式0: 方式2: 方式3: 借鑒:郭天祥《新概念51單片機C語言教程》 一、原理:51單片機,擁有兩個定時器,用來中斷計數,分別是T0和T1。而52單片機和51單片機的定時器是一樣的,只是52比51多了一個定時器/計數器T2,它們的設置都大同小異,下面我來總結各個定時器的用法。 定時器T0與T1不同之處在于它們的工作方式3不同,方式0、1、2相同。 | | | | | | | | | | | | | | 方式3,僅適用于T0,分成兩個8位計數器, 當設置成T1時停止計數 |
首先我們看要使用定時器T0應該設置的東西: 1、對中斷寄存器和定時器進行初始化:初始化函數里的內容也可以寫在頭文件里,但是為了美觀和好查閱,就把它單獨寫出來,后面在頭文件里直接調用就行。那么應該要進行初始化的設置: ①設置定時器的工作方式單片機內,有其中一個特殊寄存器叫TMOD,這是用來設置定時器工作方式的寄存器,通過軟件,將其寄存器內的D0~D7位置0或1,從而達成對定時器的操作。 寄存器TMOD | | | | | | | | | | | | | | C/  | | | | C/  | | |
如表格,這是定時器的工作方式寄存器TMOD,要更改定時器的工作方式,我們只用到M1、M2所以其他位一般置0,又因為我們使用的是T0的定時器,所以就有:
控制M1、M0將它們置1或0,即可達成操作控制方式的目的,然后轉換成16進制即方便查閱。 同理,使用定時器1時也是這么設置。注意,有時候也有使用兩個定時器T0、T1的時候,那么就是0001 0001兩個都是工作方式1。請大家舉一反三。 ②設定初值先說說總值: 以方式1為例(之后會介紹其他方式): 方式1為16位的定時器/計數器,對定時器T0來說是分成兩個寄存器(可以形象地比作容器吧,網上有比我更形象的比喻,我就不多寫了,請自行查閱):TH0為高八位,TL0為低八位,組成了16位的定時器,當低位TL0計滿就向高位TH0移一個數,然后清零。 以12Mhz的晶振來說,機器周期是1us,計滿TH0、TL0就需要216-1個數,再來一個數就“溢出”產生中斷,一次溢出也就是65536us,約等于65.5ms,如果要定時50ms的話就要給他們裝一個預裝值(初值),總值-需要值=預裝值, 也就是65536-50000=15536,預裝后,定時器從預裝值開始加值,定時器溢出中斷后,會重新從預裝值開始加值加到50ms就再產生中斷,從而達到了定時的目的。如果要定時1s就可以讓定時器中斷1000ms/50ms=20次。 另外一點,TH0和TL0中應該裝入的總數是15536,然后把15536對256求模:15536/256=60裝入TH0中,把15536對256求余:15536%256=176裝入TL0中,因為這是兩個八位28*28的容器。 所以就有了 TH0=(65535-50000)/256 TL0=(65535-50000)%256 ③開啟中斷和定時器關于中斷,需要用到中斷允許寄存器: IE
定時器中斷需要的是: 總中斷EA:用來開啟全局中斷。 ET0、1、2:各個定時器中斷位。 使用中斷位只用將其置1就行,例如EA=1;ET0=1; 打開了中斷開關只是完成了一半,還需要定時器控制寄存器: TCON
使用方法也是和中斷寄存器一樣, 定時器0運行控制位TR0:用來開啟定時器0. 把TR0置1,TR0=1;就開啟了定時器。 2、設置中斷服務程序:中斷服務程序:就是當計滿TH0、TL0時溢出申請中斷,然后單片機允許中斷時,所要發生的事情。允許后就自動跳轉到中斷服務程序,并執行。 在服務程序中,如果不裝入初值,那定時器中斷服務完成后,就會從0開始重新計時,所以要在中斷程序中重新計算并裝入初值。 然后給一個變量(變量的意義為中斷次數),變量+1,當中斷次數達到20次的時候(50ms*20次=1000ms=1s),次數清零,并且讓產生指令(例如讓二極管亮呀,讓I/O口發生什么事呀)。 3、主函數:由于有了初始化函數,所以直接調用即可(不然主函數很混亂)。 While(1);這段是為了等待函數發生,挺含糊的。 另外:一般中斷服務程序中不要寫過多的處理語句,否則程序會來不及執行代碼,下一次中斷又來襲,結果程序久而久之就亂套了。 所以while處可以改成:把if處理語句寫到while處。 附上完整程序: 二、各個定時器和工作方式:先來看看工作方式: | | | | 方式3,僅適用于T0,分成兩個8位計數器, 當設置成T1時停止計數 |
工作方式有四種:0、1、2、3。我們之前已經學習了方式1的工作方式,那么接下來就先來看看其他的工作方式: 方式0:方式0,的用法和方式1的用法一樣,但是值得注意的是: 方式0是13位的定時器,它的低位TL0是五位的,所以它的總值是28*25=8192。它能裝的值也不能那么多了,于是就裝入5ms: TH0(8192-5000)/32; TL0(8192-5000)%32; 32是5位寄存器的容量。 所以要中斷200次才能達到1s。 這個方式0可以用來做短時間中斷。 方式2:方式0和方式1,當計數溢出后,計數器變為0,所以要反復重新裝填初值,這會影響定時精度。但是方式2可以解決這個問題。 如圖,其中低位TL0是8位定時器,而TH0是常數緩沖器,當低位TL0溢出時,在溢出標志位TF0置1的同時,自動將高位TH0的常數重新裝入TL0中,讓TL0從初值開始重新計數,這樣就不用人為軟件重新裝入初值帶來的誤差,從而提高精度。 由于兩個是分開的,所以計算初值可以不用求余取模: TL0=總值-要計數的個數; TH0=總值-要計數的個數;
以11.0592MHz為晶振,那么機械周期為12x(1/11059200)≈1.085us,以計時1s為例,當要計250個數時耗時1.0851x250=271.275us,再來算計時1s要用多少次,即1000000/271.275≈3686次。 那么就是:
TL0=256-250=6; TH0=256=250=6; 由于方式2是自動裝填,已經不用人為裝填了,所以: 中斷服務程序中只有一句num++ 整個過程就是:
方式3:接下來介紹方式3,方式3不同于其他三個方式,它只能用于T0,也就是定時器0,和方式2差不多,也是把TL0、TH0分成兩個獨立的寄存器,但是TH0也參與計數,也就是兩個獨立的8位定時器/計數器。 普通的使用一樣,TL0計數溢出后置位TF0,并申請中斷,之后重裝。但是由于TL0占用了TR0和TF0,所以TH0只能占用定時器 T1的TR1和TF1。所以定時器T1一定不要用在有中斷的場合,當然,T1同樣可以正常工作在方式0、1、2下。通常這種情況,T1都被用來當做串行口的波特率發生器。 首先把T0、T1的中斷位和控制位打開: 然后分別給低位TL0和高位TH0設置中斷服務程序: 可以注意到interrupt后面的數值,這個是編譯器識別不同中斷的唯一符號: 52單片機的中斷級別
然后到主函數: 調用init(); 可以看到if語句里面的符號是>=,為什么呢?因為當if語句的值到了時,主程序停止下來判斷num1==3686是否為真,當它還在判斷的時候,num2是還在走的,于是當主程序判斷好num1的時候再去判斷num2,為時已晚,num2這時可能已經是1844或者1845或者更高的數了,所以要變成>=。
完整的Word格式文檔51黑下載地址:
51定時器.docx
(148.84 KB, 下載次數: 669)
2017-12-26 23:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|