定時器和數碼管
阿新 • • 發佈:2019-02-18
通過上節課的實驗,大家會發現,我們逐漸進入比較實質性的學習了,需要記住的內容也更多了,個別地方可能會感覺吃力。但是大家不要擔心,要有信心。這個跟小孩學走路一樣,剛開始走路不太穩,沒關係,多走幾步多練練。看視訊的時候要注意專心,一遍看不懂,思考一下,再回頭看第二遍和第三遍,沒準一下就明白了。如果三遍還看不明白,那就把不懂的問題放一放,繼續往下學兩課再回頭看一次,也可以到QQ群裡或微控制器論壇http://www.51hei.com/bbs/ 裡多諮詢一下其他的同學,討論一下,可能就會茅塞頓開。
1.1 基本數字邏輯閘電路 不管是數位電路,還是C語言,我們都會經常遇到邏輯運算和邏輯電路,在這裡我介紹一下,大家先簡單瞭解一下,知道有這麼回事,回頭遇到了,再詳細研究。名稱 | 描述 | SFR地址 |
TH0 | 定時器0高位元組 | 8CH |
TL0 | 定時器0低位元組 | 8AH |
TH1 | 定時器1高位元組 | 8DH |
TL1 | 定時器1低位元組 | 8BH |
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符號 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
位 | 符號 | 描述 |
7 | TF1 | 定時器1溢位標誌。一旦定時器1發生溢位時硬體置1。清零有兩種方式:軟體清零,或者進入定時器中斷時硬體清零。 |
6 | TR1 | 定時1執行控制位。軟體置位/清零來進行啟動/關閉定時器。 |
5 | TF0 | 定時器0溢位標誌。一旦定時器0發生溢位時硬體置1。清零有兩種方式:軟體清零,或者進入定時器中斷時硬體清零。 |
4 | TR0 | 定時0執行控制位。軟體置位/清零來進行啟動/關閉定時器。 |
3 | IE1 | 外部中斷部分,與定時器無關,暫且不看 |
2 | IT1 | |
1 | IE0 | |
0 | IT0 |
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符號 | GATE (T1) | C/T (T1) | M1 (T1) | M0 (T1) | GATE (T0) | C/T (T0) | M1 (T0) | M0 (T0) |
符號 | 描述 |
T1/T0 | 在表5-5中,標T1的表示控制定時器1的位,標T0的表示控制定時器0的位。 |
GATE | 該位被置1時為門控位。僅當’INTx’腳為高並且’TRx’控制位被置1時使能定時器’x’,定時器開始計時,當該位被清0時,只要’TRx’位被置1,定時器x就使能開始計時,不受到微控制器引腳’INTx’外部訊號的干擾,常用來測量外部訊號脈衝寬度。這是定時器一個額外功能,本節課暫不介紹。 |
C/T |
定時器或計數器選擇位。該位被清零時用作定時器功能(內部系統時鐘),被置1用作計數器功能。 |
M1 | M0 | 工作模式 | 描述 |
0 | 0 | 0 | 相容8048微控制器的13位定時器,THn的8位和TLn的5位組成一個13位定時器 |
0 | 1 | 1 | THn和TLn組成一個16位的定時器 |
1 | 0 | 2 | 8位自動重灌模式,定時器溢位後THn重灌到TLn中 |
1 | 1 | 3 | 禁用定時器1,定時器0變成2個8位定時器 |
圖5-1 定時器/計數器模式1示意圖 我帶著大家來分析一下這個示意圖,後邊如果手冊中遇到,大家也就會自己研究了。OSC框表示時鐘頻率,因為我們1個機器週期等於12個時鐘週期,所以那個d就等於12。下邊GATA右邊的那個門是一個非閘電路,再右側是一個或門,再往右是一個與閘電路,大家可以對照一下5-1節的內容。 圖上可以看出來,下邊部分電路是控制了上邊部分,那我們先來看下邊是如何控制的,我們以定時器0為例。 1、TR0和下邊或閘電路的結果要進行與門運算,TR0如果是0的話,與運算完了肯定是0,所以確定如果要讓定時器工作,TR0 = 1。 2、與門結果要想是1,那或門出來的訊號必須也得是1才行。在GATE位為1的情況下,經過一個非門變成0,或閘電路結果要想是1的話,那INT0即P3.2引腳必須是1的情況下,這個時候定時器才會工作,而INT0引腳是0的情況下,定時器不工作,這就是GATE位的作用。 3、當GATE位為0的時候,經過一個非門變成1,不管INT0引腳是什麼電平,經過或閘電路後則肯定是1,定時器就會工作。 4、要想讓定時器工作,就是加1,從圖上看有兩種方式,第一種方式是那個開關打到上邊的箭頭,就是C/T = 0的時候,一個機器週期TL就會加1一次,當開關打到下邊的箭頭,即C/T =1的時候,T0引腳即P3.4引腳來一個脈衝,TL就加1一次,這也就是計數器功能。 INT0引腳是P3.2,INT1引腳是P3.3,T0引腳是P3.4,T1引腳是P3.5,這個可以從我們KST-51開發板原理圖上看出來。 1.2.3 定時器程式應用 瞭解了定時器相關的暫存器,那麼我們下面就來做一個定時器的程式,鞏固一下我們學到的內容。我們這節課的程式先使用定時器0,在使用定時器的時候,需要以下幾個步驟: 第一步:設定特殊功能暫存器TMOD,配置好工作模式; 第二步:設定計數暫存器TH0和TL0的初值; 第三步:設定TCON,通過開啟TR0位來讓定時器開始計數。 第四步:判斷TCON暫存器的TF0位,監測定時器溢位情況。 寫程式之前,我們要先來學會計算如何用定時器定時時間。我們的晶振是11.0592M,時鐘週期就是1/11059200,機器週期就是12/11059200,我們假如要定時20ms,就是0.02秒,要經過x個機器週期得到0.02秒,我們來算一下x*12/11059200=0.02,得到x= 18432。那麼我們現在16位的定時器溢位值是65536,我們可以這樣,先給TH0和TL0一個初值,讓他們經過18432個機器週期後剛好溢位,溢位後我們可以通過檢測TF0位得知,就剛好是0.02秒。這個初值y = 65536 - 18432 = 47104,轉成16進位制就是0xB800,那麼就是TH0 = 0xB8,TL0 = 0x00。 那0.02秒我們已經定時出來了,細心的同學會發現,我們如果初值直接給一個0x0000,一直到65536溢位,定時器定時值最大也就是71ms左右,那麼我們想定時更長時間怎麼辦呢?用你小學學過的邏輯,倍數關係就可以解決此問題。 那好了,我們下面就用程式來實現以下這個功能。 #include<reg52.h> //包含暫存器的庫檔案 sbit LED = P0^0; sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; void main() { unsigned char counter = 0; ENLED = 0; ADDR0 = 0; ADDR1 = 1; ADDR2 = 1; ADDR3 = 1; LED = 1; //74HC138和LED燈初始化部分 TMOD = 0x01; //設定定時器0為模式1 TH0 = 0xB8; TL0 = 0x00; //定時值初值 TR0 = 1; //開啟定時器0 while(1) { if(1 == TF0) //判斷定時器0是否溢位 { TF0 = 0; TH0 = 0xB8; //一旦溢位後,重新賦值 TL0 = 0x00; counter++; if(50 == counter) //判斷定時器0溢位是否達到50次 { counter = 0; //counter清0,重新計數 LED = !LED; //LED取反操作,0-->1,1-->0 } } } } 程式都有註釋,不難理解,這裡要解釋一個地方,就是兩次if判斷,細心的同學會發現,if(1 == TF0)這句,我把1寫前邊,這個地方我推薦新手按照我這樣來寫,因為如果我們寫if(TF0 == 1),作為新手來說,不小心丟掉一個’=’號後,寫成if(TF0 = 1),這樣實際上在語法上是可以通過的,我們用的Keil4還會出一個警告說明一下,Keil以前的版本以及一些其他軟體,可能根本不會出任何錯誤或者警告提示,但是這樣產生的Hex檔案下載到微控制器裡邊,程式就錯了,大家可以改改試試看。 本程式實現的結果是我們板子上最右邊的小燈點亮持續一秒,熄滅持續一秒,也就是以0.5HZ的頻率進行閃爍。 1.3 數碼管學習 小燈是一種簡單的LED,給我們視覺效果只能通過亮和滅來表達簡單資訊。而這節課我們要來學習一種表達更加明確的器件,數碼管。 1.3.1 數碼管的基本介紹 先給大家提供一張原理圖看一下,如圖5-1所示。 圖5-2 數碼管原理圖 這是比較常見的數碼管的原理圖,我們板子上一共有6只數碼管。前邊有了LED小燈的學習,數碼管學習就會輕鬆的多了。從圖5-1能看出來,數碼管共有a,b,c,d,e,f,g,dp這8個段,而實際上,這8個段每一段都是一個LED小燈,所以數碼管就是由8個LED小燈所組成的。我們看一下數碼管內部結構圖5-2。 圖5-3 數碼管結構圖 數碼管分為共陽數碼管和共陰數碼管,所謂的共陰數碼管就是8只LED小燈的陰極是接在一起的,也就是陰極是公共端,由陽極來控制小燈是否亮滅。同理,共陽數碼管就是陽極是接到一起的,大家可以仔細研究下圖5-2。細心的同學也會發現,數碼管上邊有2個com,實際上就是我們數碼管的公共端。為什麼有2個,我個人認為,一方面有2個可以起到對稱的效果,剛好是10個引腳,另外一個方面,公共端通過的電流較大,我們初中就學過,並聯電路電流之和等於總電流,用2個com可以把公共電流平均到2個引腳上去,降低線路承受的電流。 從我們板子的電路圖上能看出來,我們所用的數碼管是共陽數碼管,如圖5-3所示。
圖5-4 共陽數碼管電路 他們的com是接到了正極上,當然了,和LED小燈電路類似,也是由74HC138控制了三極體的導通來控制整個數碼管的電流,我們先來看DS1這個數碼管。原理圖上可以看出來,控制DS1的三極體是Q17,控制Q17的引腳是LEDS0,對應到74HC138上邊就是Y0端的輸出。
圖5-5 74HC138控制圖 我們現在的目的是讓LEDS0這個引腳輸出低電平,相信大家現在可以獨立根據前邊學到的內容把ADDR0,ADDR1,ADDR2,ADDR3,ENLED這4個輸入狀態寫出來,現在大家不要偷懶,都去根據138的手冊去寫一下,不需要你記住這些結論,但是遇到就寫一次,鍛鍊過幾次後,遇到同類晶片自己就知道如何去解決問題了。 數碼管通常是用來顯示數字的,我們板子上的6個數碼管,習慣上我們稱之為6位,那控制位選擇的就是74HC138了。而數碼管內部的8個LED小燈我們稱之為數碼管的段,那麼數碼管的段選擇(即該段的亮滅)是通過P0口控制,經過74HC245驅動。 1.3.2 數碼管的真值表 數碼管的8個段,我們直接當成8個LED小燈來控制,那就是a、b、c、d、e、f、g、dp一共8個LED小燈。我們通過圖5-1可以輕而易舉的看出來,如果我們點亮b和c這兩個LED小燈,也就是數碼管的b段和c段,其他的所有的段都熄滅的話,就可以讓數碼管DS1顯示一個數字1,那麼這個時候實際上P0的值的二進位制就是0b11111001,十六進位制就是0xF9。也有可以自動生成數碼管段位碼的軟體可以從http://www.51hei.com/mcudown/ 下載檔名是"數碼管段位設碼程式.rar",那麼我們寫一個程式進去,看看讓數碼管顯示一下看看。 #include<reg52.h> //包含暫存器的庫檔案 sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; void main() { unsigned char j = 0; unsigned int i = 0; ENLED = 0; ADDR0 = 0; ADDR1 = 0; ADDR2 = 0; ADDR3 = 1; //74HC138開啟三極體Q17 while(1) //程式死迴圈 { P0 = 0xF9; //開啟數碼管b和c段 } } 大家把這個程式編譯一下,下載到微控制器裡會發現,最右側的數碼管成功顯示1這個數字。 同樣的方法,我們可以把其他的數字都成功的在數碼管上顯示出來,而數碼管顯示的數字對應給P0的賦值,我們叫做數碼管的真值表。我們來列一下我們這個電路圖的數碼管真值表,注意,這個真值表裡顯示的數字都不帶小數點。 表5-1 數碼管真值表
數字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
真值表 | 0xC0 | 0xF9 | 0xA4 | 0xB0 | 0x99 | 0x92 | 0x82 | 0xF8 |
數字 | 8 | 9 | A | B | C | D | E | F |
真值表 | 0x80 | 0x90 | 0x88 | 0x83 | 0xC6 | 0xA1 | 0x86 | 0x8E |