单片机定时器实验两位倒计时秒表_第5章 定时器与数码管基础
通過上節課的實驗,大家會發現,我們逐漸進入比較實質性的學習了,需要記住的內容也更多了,個別地方可能會感覺吃力。但是大家不要擔心,要有信心。這個跟小孩學走路一樣,剛開始走得不太穩,沒關系,多走幾步多練練。看教材的時候要注意專心,一遍看不懂,思考一下,再回頭看第二遍和第三遍,沒準一下就明白了。如果三遍還看不明白,那就把不懂的問題放一放,繼續往下學兩課然后再回頭看一次,也可以到群里或者論壇里多咨詢一下其他的同學,討論一下,可能就會茅塞頓開了。
5.1 邏輯電路與邏輯運算
在數字電路,我們經常會遇到邏輯電路,而在C語言中,我們則經常用到邏輯運算。二者在原理上是相互關聯的,我們在這里就先簡單介紹一下,隨著學習的深入,再慢慢加深理解。
首先,在“邏輯”這個概念范疇內,存在真和假這兩個邏輯值,而將其對應到數字電路或C語言中,就變成了“非0值”和“0值”這兩個值,即邏輯上的“假”就是數字電路或C語言中的“0”這個值,而邏輯“真”就是其它一切“非0值”。
然后,我們來具體分析一下幾個主要的邏輯運算符。我們假定有2個字節變量:A和B,二者進行某種邏輯運算后的結果為F。
以下邏輯運算符都是按照變量整體值進行運算的,通常就叫做邏輯運算符:
&& 邏輯與。F = A && B,當A、B的值都為真(即非0值,下同)時,其運算結果F為真(具體數值為1,下同);當A、B值任意一個為假(即0,下同)時,結果F為假(具體數值為0,下同)。
|| 邏輯或。F = A || B,當A、B值任意一個為真時,其運算結果F為真;當A、B值都為假時,結果F為假。
! 邏輯非,F = !A,當A值為假時,其運算結果F為真;當A值為真時,結果F為假。
以下邏輯運算符都是按照變量內的每一個位來進行運算的,通常就叫做位運算符:
& 按位與,F = A & B,將A、B兩個字節中的每一位都進行與運算,再將得到的每一位結果組合為總結果F,例如A = 0b11001100,B = 0b11110000,則結果F就等于0b11000000。
| 按位或,F = A | B,將A、B兩個字節中的每一位都進行或運算,再將得到的每一位結果組合為總結果F,例如A = 0b11001100,B = 0b11110000,則結果F就等于0b11111100。
~ 按位取反,F = ~A,將A字節內的每一位進行非運算(就是取反),再將得到的每一位結果組合為總結果F,例如A = 0b11001100,則結果F就等于0b00110011;這個運算符我們在前面的流水燈實驗里已經用過了,現在再回頭看一眼,是不是清楚多了。
^ 按位異或,異或的意思是,如果運算雙方的值不同(即相異)則結果為真,雙方值相同則結果為假。在C語言里沒有按變量整體值進行的異或運算,所以我們僅以按位異或為例,F = A ^ B,A = 0b11001100,B = 0b11110000,則結果F就等于0b00111100。
我們今后要看資料或芯片手冊的時候,會經常遇到一些電路符號,圖5-1所示就是數字電路中的常用符號,知道這些符號有利于我們理解器件的邏輯結構,尤其重點認識圖5-1中的國外流行圖形符號。在這里我們先簡單看一下,如果日后遇到了可以到這里來查閱。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
圖5-1? 邏輯電路符號
5.2 定時器的學習
定時器是單片機系統的一個重點,但并不是難點,大家一定要完全理解并且熟練掌握定時器的應用。
5.2.1 定時器的初步認識
時鐘周期:時鐘周期T是時序中最小的時間單位,具體計算的方法就是1/時鐘源頻率,我們KST-51單片機開發板上用的晶振是11.0592M,那么對于我們這個單片機系統來說,時鐘周期=1/11059200秒。
機器周期:我們的單片機完成一個操作的最短時間。機器周期主要針對匯編語言而言,在匯編語言下程序的每一條語句執行所使用的時間都是機器周期的整數倍,而且語句占用的時間是可以計算出來的,而C語言一條語句的時間是不確定的,受到諸多因素的影響。51單片機系列,在其標準架構下一個機器周期是12個時鐘周期,也就是12/11059200秒。現在有不少增強型的51單片機,其速度都比較快,有的1個機器周期等于4個時鐘周期,有的1個機器周期就等于1個時鐘周期,也就是說大體上其速度可以達到標準51架構的3倍或12倍。因為我們是講標準的51單片機,所以我們后邊的課程如果遇到這個概念,全部是指12個時鐘周期。
這兩個概念了解即可,下邊就來我們的重頭戲,定時器和計數器。定時器和計數器是單片機內部的同一個模塊,通過配置SFR(特殊功能寄存器)可以實現兩種不同的功能,我們大多數情況下是使用定時器功能,因此我們的課程也是主要來講定時器功能,計數器功能大家自己了解下即可。
顧名思義,定時器就是用來進行定時的。定時器內部有一個寄存器,我們讓它開始計數后,這個寄存器的值每經過一個機器周期就會自動加1,因此,我們可以把機器周期理解為定時器的計數周期。就像我們的鐘表,每經過一秒,數字自動加1,而這個定時器就是每過一個機器周期的時間,也就是12/11059200秒,數字自動加1。還有一個特別注意的地方,就是鐘表是加到60后,秒就自動變成0了,這種情況在單片機或計算機里我們稱之為溢出。那定時器加到多少才會溢出呢?后面會講到定時器有多種工作模式,分別使用不同的位寬(指使用多少個二進制位),假如是16位的定時器,也就是2個字節,最大值就是65535,那么加到65535后,再加1就算溢出,如果有其他位數的話,道理是一樣的,對于51單片機來說,溢出后,這個值會直接變成0。從某一個初始值開始,經過確定的時間后溢出,這個過程就是定時的含義。
5.2.2 定時器的寄存器
標準的51單片機內部有T0和T1這兩個定時器,T就是Timer的縮寫,現在很多51系列單片機還會增加額外的定時器,在這里我們先講定時器0和1。前邊提到過,對于單片機的每一個功能模塊,都是由它的SFR,也就是特殊功能寄存器來控制。與定時器有關的特殊功能寄存器,有以下幾個,大家不需要去記憶這些寄存器的名字和作用,你只要大概知道就行,用的時候,隨時可以查手冊,找到每個寄存器的名字和每個寄存器所起到的作用。
表5-1的寄存器是存儲定時器的計數值的。TH0/TL0用于T0,TH1/TL1用于T1。
表5-1? 定時值存儲寄存器
名稱 | 描述 | SFR地址 | 復位值 |
TH0 | 定時器0高字節 | 0x8C | 0x00 |
TL0 | 定時器0低字節 | 0x8A | 0x00 |
TH1 | 定時器1高字節 | 0x8D | 0x00 |
TL1 | 定時器1低字節 | 0x8B | 0x00 |
表5-2是定時器控制寄存器TCON的位分配,表5-3是則是對每一位的具體含義的描述。
表5-2? TCON——定時器控制寄存器的位分配(地址0x88、可位尋址)
表5-3?? TCON——定時器控制寄存器的位描述
位 | 符號 | 描述 |
7 | TF1 | 定時器1溢出標志。一旦定時器1發生溢出時硬件置1。清零有兩種方式:軟件清零,或者進入定時器中斷時硬件清零。 |
6 | TR1 | 定時器1運行控制位。軟件置位/清零來進行啟動/停止定時器。 |
5 | TF0 | 定時器0溢出標志。一旦定時器0發生溢出時硬件置1。清零有兩種方式:軟件清零,或者進入定時器中斷時硬件清零。 |
4 | TR0 | 定時器0運行控制位。軟件置位/清零來進行啟動/停止定時器。 |
3 | IE1 | 外部中斷部分,與定時器無關,暫且不看。 |
2 | IT1 | |
1 | IE0 | |
0 | IT0 |
大家注意在表5-3中的描述中,只要寫到硬件置1或者清0的,就是指一旦符合條件,單片機將自動完成的動作,只要寫軟件置1或者清0的,是指我們必須用程序去完成這個動作,后續遇到此類描述就不再另做說明了。
對于TCON這個SFR,其中有TF1、TR1、TF0、TR0這4位需要我們理解清楚,它們分別對應于T1和T0,我們以定時器1為例講解,那么定時器0同理。先看TR1,當我們程序中寫TR1 = 1以后,定時器值就會每經過一個機器周期自動加1,當我們程序中寫TR1 = 0以后,定時器就會停止加1,其值會保持不變化。TF1,這個是一個標志位,他的作用是告訴我們定時器溢出了。比如我們的定時器設置成16位的模式,那么每經過一個機器周期,TL1加1一次,當TL1加到255后,再加1,TL1變成0,TH1會加1一次,如此一直加到TH1和TL1都是255(即TH1和TL1組成的16位整型數為65535)以后,再加1一次,就會溢出了,TH1和TL1同時都變為0,只要一溢出,TF1馬上自動變成1,告訴我們定時器溢出了,僅僅是提供給我們一個信號,讓我們知道定時器溢出了,它不會對定時器是否繼續運行產生任何影響。
本節開頭我們就提到了定時器有多種工作模式,工作模式的選擇就由TMOD來控制,TMOD的位分配和描述見表5-4到5-6所示,TMOD的位功能如表5-5所示。
表5-4? TMOD——定時器模式寄存器的位分配(地址0x89、不可位尋址)
表5-5? TMOD——定時器模式寄存器的位描述
符號 | 描述 |
T1/T0 | 在表5-4中,標T1的表示控制定時器1的位,標T0的表示控制定時器0的位。 |
GATE | 該位被置1時為門控位。僅當‘INTx’腳為高并且‘TRx’控制位被置1時使能定時器‘x’,定時器開始計時,當該位被清0時,只要‘TRx’位被置1,定時器x就使能開始計時,不受到單片機引腳‘INTx’外部信號的干擾,常用來測量外部信號脈沖寬度。這是定時器一個額外功能,本節課暫不介紹。 |
C/T | 定時器或計數器選擇位。該位被清零時用作定時器功能(內部系統時鐘),被置1用作計數器功能。 |
表5-6? TMOD——定時器模式寄存器M1/M0工作模式
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-2的TCON最后標注了“可位尋址”,而表5-4的TMOD標注的是“不可位尋址”。意思就是說:比如TCON有一個位叫TR1,我們可以在程序中直接進行TR1 = 1這樣的操作。但對TMOD里的位比如(T1)M1 = 1這樣的操作就是錯誤的。我們要操作就必須一次操作這整個字節,也就是必須一次性對TMOD所有位操作,不能對其中某一位單獨進行操作,那么我們能不能只修改其中的一位而不影響其它位的值呢?當然可以,在后續課程中你就會學到方法的,現在就先不關心它了。
表5-6列出的就是定時器的4種工作模式,其中模式0是為了兼容老的8048系列單片機而設計的,現在的51幾乎不會用到這種模式,而模式3根據我的應用經驗,它的功能用模式2完全可以取代,所以基本上也是不用的,那么我們就重點來學習模式1和模式2。
模式1,是THn和TLn組成了一個16位的定時器,計數范圍是0~65535,溢出后,只要不對THn和TLn重新賦值,則從0開始計數。模式2,是8位自動重裝載模式,只有TLn做加1計數,計數范圍0~255,THn的值并不發生變化,而是保持原值,TLn溢出后,TFn就直接置1了,并且THn原先的值直接賦給TLn,然后TLn從新賦值的這個數字開始計數。這個功能可以用來產生串口的通信波特率,我們講串口的時候要用到,本章節我們重點來學習模式1。為了加深大家理解定時器的原理,我們來看一下他的模式1的電路示意圖5-2。
圖5-2? 定時器/計數器模式1示意圖
我帶領大家一起來分析一遍這個示意圖,日后如果再遇到類似的圖,大家就可以自己研究了。OSC框表示時鐘頻率,因為1個機器周期等于12個時鐘周期,所以那個d就等于12。下邊GATE右邊的那個門是一個非門電路,再右側是一個或門,再往右是一個與門電路,大家可以對照一下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一次,這也就是計數器功能。
5.2.3 定時器的應用
了解了定時器相關的寄存器,那么我們下面就來做一個定時器的程序,鞏固一下我們學到的內容。我們這節課的程序先使用定時器0,在使用定時器的時候,需要以下幾個步驟:
第一步:設置特殊功能寄存器TMOD,配置好工作模式。
第二步:設置計數寄存器TH0和TL0的初值。
第三步:設置TCON,通過TR0置1來讓定時器開始計數。
第四步:判斷TCON寄存器的TF0位,監測定時器溢出情況。
寫程序之前,我們要先來學會計算如何用定時器定時時間。我們的晶振是11.0592M,時鐘周期就是1/11059200,機器周期是12/11059200,假如要定時20ms,就是0.02秒,要經過x個機器周期得到0.02秒,我們來算一下x*12/11059200=0.02,得到x= 18432。16位定時器的溢出值是65536(因65535再加1才是溢出),于是我們就可以這樣操作,先給TH0和TL0一個初始值,讓它們經過18432個機器周期后剛好達到65536,也就是溢出,溢出后可以通過檢測TF0的值得知,就剛好是0.02秒。那么初值y = 65536 - 18432 = 47104,轉成16進制就是0xB800,也就是TH0 = 0xB8,TL0 = 0x00。
這樣0.02秒的定時我們就做出來了,細心的同學會發現,如果初值直接給一個0x0000,一直到65536溢出,定時器定時值最大也就是71ms左右,那么我們想定時更長時間怎么辦呢?用你小學學過的邏輯,倍數關系就可以解決此問題。
好了,我們下面就用程序來實現這個功能。
程序中都寫了注釋,結合前幾章學的內容,自己分析一下,不難理解。本程序實現的結果是開發板上最右邊的小燈點亮一秒,熄滅一秒,也就是以0.5Hz的頻率進行閃爍。
5.3 數碼管的學習
LED小燈是一種簡單的LED,只能通過亮和滅來表達簡單的信息。而這節課我們要來學習一種能表達更復雜信息的器件——LED數碼管。
5.3.1 數碼管的基本介紹
先給大家提供一張原理圖看一下,如圖5-3所示。
圖5-3? 數碼管原理圖
這是比較常見的數碼管的原理圖,我們板子上一共有6個數碼管。前邊有了LED小燈的學習,數碼管學習就會輕松的多了。從圖5-3可以看出來,數碼管共有a、b、c、d、e、f、g、dp這么8個段,而實際上,這8個段每一段都是一個LED小燈,所以一個數碼管就是由8個LED小燈組成的。我們看一下數碼管內部結構的示意圖,如圖5-4。
圖5-4? 數碼管結構示意圖
數碼管分為共陽和共陰兩種,共陰數碼管就是8只LED小燈的陰極是連接在一起的,陰極是公共端,由陽極來控制單個小燈的亮滅。同理,共陽數碼管就是陽極接在一起,大家可以認真研究下圖5-4。細心的同學會發現,圖5-3的數碼管上邊有2個com,這就是我們數碼管的公共端。為什么有2個呢,一方面是2個可以起到對稱的效果,剛好是10個引腳,另外一個方面,公共端通過的電流較大,我們初中就學過,并聯電路電流之和等于總電流,用2個com可以把公共電流平均到2個引腳上去,降低單條線路承受的電流。
從我們開發板的電路圖上能看出來,我們所用的數碼管都是共陽數碼管,一共有6個,如圖5-5所示。
圖5-5? KST-51數碼管電路
6個數碼管的com都是接到了正極上,當然了,和LED小燈電路一樣,也是由74HC138控制三極管的導通來控制整個數碼管的使能。先來看最右邊的DS1這個數碼管,原理圖上可以看出,控制DS1的三極管是Q17,控制Q17的引腳是LEDS0,對應到74HC138上邊就是U3的Y0輸出,如圖5-6所示。
圖5-6? 74HC138控制圖
我們現在的目的是讓LEDS0這個引腳輸出低電平,相信大家現在可以根據前邊學過的知識獨立把ADDR0、ADDR1、ADDR2、ADDR3、ENLED這4個所需輸入的值寫出來了,現在大家不要偷懶,根據74HC138的手冊去寫一下,不需要你記住這些結論,但是遇到就寫一次,鍛煉過幾次后,遇到同類芯片自己就知道如何去解決問題了。
數碼管通常是用來顯示數字的,我們板子上有6個數碼管,習慣上稱之為6位,那控制位選擇的就是74HC138了。而數碼管內部的8個LED小燈我們稱之為數碼管的段,那么數碼管的段選擇(即該段的亮滅)是通過P0口控制,經過74HC245驅動。
5.3.2 數碼管的真值表
數碼管的8個段,我們直接當成8個LED小燈來控制,那就是a、b、c、d、e、f、g、dp一共8個LED小燈。我們通過圖5-3可以看出,如果點亮b和c這兩個LED小燈,也就是數碼管的b段和c段,其他的所有的段都熄滅的話,就可以讓數碼管顯示出一個數字1,那么這個時候實際上P0的值就是0b11111001,十六進制就是0xF9。那么我們寫一個程序進去,來看一看數碼管顯示的效果。
大家把這個程序編譯一下,并下載到單片機中,就可以看到程序運行的結果是在最右側的數碼管上顯示了一個數字1。
用同樣的方法,我們可以把其他的數字字符都在數碼管上顯示出來,而數碼管顯示的數字字符對應給P0的賦值,我們叫做數碼管的真值表。我們來列一下我們這個電路圖的數碼管真值表,注意,這個真值表里顯示的數字都不帶小數點的,如表5-7。
表5-7 數碼管真值表
字符 | 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 |
大家可以把上邊那個用數碼管顯示數字1程序中的P0的賦值隨便修改成表5-7真值表中的數值,看看顯示的數字的效果。
5.3.3 數碼管的靜態顯示
在第三章我們學習了74HC138,了解到74HC138在同一時刻只能讓一個輸出口為低電平,也就是說在一個時刻內,我們只能使能一個數碼管,并根據我們給出的P0的值來改變這個數碼管的顯示字符,我們可以將此理解為數碼管的靜態顯示。
數碼管靜態顯示是對應動態顯示而言的,靜態顯示對于一兩個數碼管還行,多個數碼管,靜態顯示實現的意義就沒有了。這節課我們先用一個數碼管的靜態顯示來實現一個簡單的秒表,為下節課的動態顯示打下基礎。
先來介紹一個51單片機的關鍵字code。我們前邊課程定義變量的時候,一般用到unsigned char或者unsigned int這兩個關鍵字,這樣定義的變量都是放在我們的單片機的RAM中,我們在程序中可以隨意去改變這些變量的值。但是還有一種數據,我們在程序中要使用,但是卻不會改變它的值,定義這種數據時可以加一個code關鍵字修飾一下,這個數據就會存儲到我們的程序空間Flash中,這樣可以大大節省單片機的RAM的使用量,畢竟我們的單片機RAM空間比較小,而程序空間則大的多。那么現在要使用的數碼管真值表,我們只會使用它們的值,而不需要改變它們,就可以用code關鍵字把它放入Flash中了,具體程序代碼如下。
5.4 練習題
1、熟練掌握單片機定時器的原理和應用方法。
2、通過研究定時器模式1的示意圖,自己打開STC89C52RC數據手冊的定時器部分,獨立研究模式0、模式2和模式3的示意圖,鍛煉一下研究示意圖的能力。
3、使用定時器來實現左右移動的流水燈程序。
4、了解數碼管的原理,掌握數碼管的真值表的計算方法。
5、編程實現數碼管靜態顯示秒表的倒計時。
金沙灘工作室
長按識別關注
知識共享|助力夢想
總結
以上是生活随笔為你收集整理的单片机定时器实验两位倒计时秒表_第5章 定时器与数码管基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 企工宝是什么
- 下一篇: 相互宝如何申请互助金