單片機數字邏輯門(mén)電路和定時(shí)器
不管是數字電路,還是C語(yǔ)言,我們都會(huì )經(jīng)常遇到邏輯運算和邏輯電路,在這里我介紹一下,大家先簡(jiǎn)單了解一下,知道有這么回事,回頭遇到了,再詳細研究。
本文引用地址:http://dyxdggzs.com/article/201808/385209.htm首先,在“邏輯”這個(gè)概念范疇內,存在真和假這兩個(gè)邏輯值,而將其對應到數字電路或C語(yǔ)言中,就變成了“非0值”和“0值”這兩個(gè)值,即邏輯上的“假”就是數字電路或C語(yǔ)言中的“0”這個(gè)值,而邏輯“真”就是其它一切“非0值”。
然后,我們來(lái)具體分析一下幾個(gè)主要的邏輯運算符。我們假定有2個(gè)字節變量:A和B,二者進(jìn)行某種邏輯運算后的結果為F。
以下邏輯運算符都是按照變量整體值進(jìn)行運算的,通常就叫做邏輯運算符:
:邏輯與,F = A B,當A、B的值都為真(即非0值,下同)時(shí),其運算結果F為真(具體數值為1,下同);當A、B值任意一個(gè)為假(即0,下同)時(shí),結果F為假(具體數值為0,下同)。
||:邏輯或,F = A || B,當A、B值任意一個(gè)為真時(shí),其運算結果F為真;當A、B值都為假時(shí),結果F為假。
! :邏輯非,F = !A,當A值為假時(shí),其運算結果F為真;當A值為真時(shí),結果F為假。
以下邏輯運算符都是按照變量?jì)鹊拿恳粋€(gè)位來(lái)進(jìn)行運算的,通常就叫做位運算符:
:按位與,F = A B,將A、B兩個(gè)字節中的每一位都進(jìn)行與運算,再將得到的每一位結果組合為總結果F,例如A = 0b11001100,B = 0b11110000,則結果F就等于0b11000000。
| :按位或,F = A | B,將A、B兩個(gè)字節中的每一位都進(jìn)行或運算,再將得到的每一位結果組合為總結果F,例如A = 0b11001100,B = 0b11110000,則結果F就等于0b11111100。
~ :按位取反,F = ~A,將A字節內的每一位進(jìn)行非運算(就是取反),再將得到的每一位結果組合為總結果F,例如,A = 0b11001100,則結果F就等于0b00110011;這個(gè)運算符我們在前面的流水燈實(shí)驗里已經(jīng)用過(guò)了,現在再回頭看一眼,是不是清楚多了。
^ :按位異或,異或的意思是,如果運算雙方的值不同(即相異)則結果為真,雙方值相同則結果為假。在C語(yǔ)言里沒(méi)有按變量整體值進(jìn)行的異或運算,所以我們僅以按位異或為例,F = A ^ B,A = 0b11001100,B = 0b11110000,則結果F就等于0b00111100。
我們今后要看資料或芯片手冊的時(shí)候,會(huì )經(jīng)常遇到一些電路符號,表1就是數字電路中的常用符號,知道這些符號有利于我們理解器件的邏輯結構,尤其重點(diǎn)認識以下表中的“國外流行圖形符號”。在這里我們先簡(jiǎn)單看一下,后邊遇到了知道到這里查閱就可以了。
表1 數字邏輯門(mén)電路

二、定時(shí)器的學(xué)習
定時(shí)器是單片機的重點(diǎn)中的重點(diǎn),但不是難點(diǎn),大家一定要完全理解并且熟練掌握定時(shí)器的應用。
定時(shí)器的初步認識
時(shí)鐘周期:時(shí)鐘周期T是時(shí)序中最小的時(shí)間單位具體計算的方法就是1/時(shí)鐘源,如果大家用的晶振是11.0592M,那么對于這個(gè)單片機系統來(lái)說(shuō),時(shí)鐘周期=1/11059200秒。
機器周期:我們的單片機完成一個(gè)操作的最短時(shí)間。機器周期主要針對匯編語(yǔ)言而言,在匯編語(yǔ)言下程序的每一條語(yǔ)句執行所使用的時(shí)間都是機器周期的整數倍,而且語(yǔ)句占用的時(shí)間是可以計算出來(lái)的,而C語(yǔ)言一條語(yǔ)句的時(shí)間是不可計算的。51單片機系列,在其標準架構下一個(gè)機器周期是12個(gè)時(shí)鐘周期,也就是12/11059200秒?,F在有不少增強型的51單片機,其速度都比較塊,有的1個(gè)機器周期等于4個(gè)時(shí)鐘周期,有的1個(gè)機器周期就等于1個(gè)時(shí)鐘周期,也就是說(shuō)大體上其速度可以達到標準51架構的3倍或12倍。因為我們是講標準的51單片機,所以我們后邊的課程如果遇到這個(gè)概念,全部是指12個(gè)時(shí)鐘周期。
這兩個(gè)概念了解即可,下邊就來(lái)我們的重頭戲,定時(shí)器和計數器。定時(shí)器和計數器是單片機內部的同一個(gè)模塊,通過(guò)配置SFR(特殊功能寄存器)可以實(shí)現兩種不同的功能,我們大多數情況下是使用定時(shí)器功能,因此我們的課程也是主要來(lái)講定時(shí)器功能,計數器功能大家自己了解下即可。
顧名思義,定時(shí)器就是用來(lái)進(jìn)行定時(shí)的。定時(shí)器內部有一個(gè)寄存器,我們讓它開(kāi)始計數后,這個(gè)寄存器的值每經(jīng)過(guò)一個(gè)機器周期就會(huì )加1一次,因此,我們可以把機器周期理解為定時(shí)器的計數周期。我們的秒表,每經(jīng)過(guò)一秒,數字加1,而這個(gè)定時(shí)器就是每過(guò)一個(gè)機器周期的時(shí)間,也就是12/11059200秒,數字加1。還有一個(gè)特別注意的地方,就是秒表是加到60后,秒就自動(dòng)變成0了,這種情況在單片機和計算機里我們稱(chēng)之為溢出。那定時(shí)器加到多少才會(huì )溢出呢?定時(shí)器有幾種模式,假如是16位的定時(shí)器,也就是2個(gè)字節,最大值就是65535,那么加到65535后,再加1就算溢出,如果有其他位數的話(huà),道理是一樣的,對于51單片機來(lái)說(shuō),溢出后,這個(gè)值會(huì )直接變成0。從某一個(gè)初值,經(jīng)過(guò)計算確定的時(shí)間后溢出,這個(gè)過(guò)程就是其定時(shí)的含義。
定時(shí)器的寄存器描述
標準的51里邊只有定時(shí)器0和定時(shí)器1這兩個(gè)定時(shí)器,現在很多單片機也有多個(gè)定時(shí)器的,在這里我們先講定時(shí)器0和1。那么我前邊提到過(guò),對于單片機的每一個(gè)功能模塊,都是由他的SFR,也就是特殊功能寄存器來(lái)控制。而和定時(shí)器有關(guān)的特殊功能寄存器,有以下幾個(gè),大家不需要去記憶這些寄存器的名字和作用,你只要大概知道就行,用的時(shí)候,隨時(shí)可以查手冊,找到每個(gè)寄存器的名字和每個(gè)寄存器所起到的作用。
表2 定時(shí)值存儲寄存器

表3 TCON--定時(shí)器/計數器控制寄存器的位分配(地址:88H)
可位尋址;復位值:0x00;復位源:任何復位

表4 TCON--定時(shí)器/計數器控制寄存器的位描述

大家注意在表4中的描述中,只要寫(xiě)到硬件置1或者清0的,就是指一旦符合條件,單片機自動(dòng)完成的動(dòng)作,只要寫(xiě)軟件置1或者清0的,是指我們用程序去完成這個(gè)動(dòng)作,后邊課程中不再做說(shuō)明。
表2中的寄存器,是存儲計數器的計數值的,兩個(gè)字節的用于定時(shí)器1,兩個(gè)字節用于定時(shí)器0。
表3中有TF1、TR1、TF0、TR0這4位需要我們理解清楚。兩位定時(shí)器1的,兩位定時(shí)器0的,我們只解釋定時(shí)器1的,定時(shí)器0的同理。先看TR1,當我們程序中寫(xiě)TR1 = 1以后,定時(shí)器值就會(huì )每經(jīng)過(guò)一個(gè)機器周期加1,當我們程序中寫(xiě)TR1 = 0以后,定時(shí)器值就會(huì )保持不變化。TF1,這個(gè)是一個(gè)標志位,他的作用是告訴我們定時(shí)器溢出了。比如我們的定時(shí)器設置成16位的定時(shí)器,那么每經(jīng)過(guò)一個(gè)機器周期,TL1加1一次,當TL1加到255后,再加1,TL1變成0,TH1會(huì )加1一次,如此一直加到TH1和TL1都是255(即TH1和TL1組成的16位整型數為65535)以后,再加1一次,那么就會(huì )溢出,TH1和TL1同時(shí)都變?yōu)?,只要一溢出,TF1馬上自動(dòng)變成1,告訴我們定時(shí)器溢出了,僅僅是提供給我們一個(gè)信號,讓我們知道定時(shí)器溢出了,它不會(huì )對定時(shí)器是否繼續運行產(chǎn)生任何影響。
表5 TMOD--定時(shí)器方式控制寄存器的位分配(地址 89H)
不可位尋址;復位值:0x00;復位源:任何復位

細心的同學(xué)會(huì )發(fā)現,TCON那個(gè)地方標注的是“可位尋址”,TMOD這里標注的是“不可位尋址”。這個(gè)地方的意思就是比如TCON有一位TR1,我們可以在程序中直接進(jìn)行TR1 = 1;這樣操作。但是(T1)M1 = 1;這樣的操作就是錯誤的。我們要操作就必須一次操作一個(gè)字節,就是必須一次性對TMOD所有位操作,不能對其中某一位單獨進(jìn)行操作。
表6 TMOD--定時(shí)器/計數器方式控制寄存器的位描述

表7 TMOD--定時(shí)器方式控制寄存器M1/M0工作模式

以上這4種模式的配置,其中模式0是為了兼容老的8048單片機而設的,現在的51幾乎不會(huì )用到這種模式,而模式3根據我的應用經(jīng)驗,他的功能模式2完全可以取代,所以基本上也是不用,那么我們重點(diǎn)就學(xué)習模式1和模式2。
模式1就是THn和TLn組成了一個(gè)16位的定時(shí)器,取值范圍是0到65535,溢出后,只要不對THn和TLn重新賦值,則從0開(kāi)始計數。模式2的功能是自動(dòng)裝載,就是TLn溢出后,TFn就直接置1了,并且THn的值直接賦給TLn,然后TLn從新賦值的這個(gè)數字開(kāi)始計數。這個(gè)功能可以用來(lái)產(chǎn)生串口的通信波特率,我們講串口的時(shí)候要用到,本章節我們重點(diǎn)來(lái)學(xué)習模式1。為了加深大家理解這個(gè)定時(shí)器原理,我們來(lái)看一下他的模式1的電路示意圖1。
圖1 定時(shí)器/計數器模式1示意圖

我帶著(zhù)大家來(lái)分析一下這個(gè)示意圖,后邊如果手冊中遇到,大家也就會(huì )自己研究了。OSC框表示時(shí)鐘頻率,因為我們1個(gè)機器周期等于12個(gè)時(shí)鐘周期,所以那個(gè)d就等于12。下邊GATA右邊的那個(gè)門(mén)是一個(gè)非門(mén)電路,再右側是一個(gè)或門(mén),再往右是一個(gè)與門(mén)電路。
圖上可以看出來(lái),下邊部分電路是控制了上邊部分,那我們先來(lái)看下邊是如何控制的,我們以定時(shí)器0為例。
1、TR0和下邊或門(mén)電路的結果要進(jìn)行與門(mén)運算,TR0如果是0的話(huà),與運算完了肯定是0,所以確定如果要讓定時(shí)器工作,TR0 = 1。
2、與門(mén)結果要想是1,那或門(mén)出來(lái)的信號必須也得是1才行。在GATE位為1的情況下,經(jīng)過(guò)一個(gè)非門(mén)變成0,或門(mén)電路結果要想是1的話(huà),那INT0即P3.2引腳必須是1的情況下,這個(gè)時(shí)候定時(shí)器才會(huì )工作,而INT0引腳是0的情況下,定時(shí)器不工作,這就是GATE位的作用。
3、當GATE位為0的時(shí)候,經(jīng)過(guò)一個(gè)非門(mén)變成1,不管INT0引腳是什么電平,經(jīng)過(guò)或門(mén)電路后則肯定是1,定時(shí)器就會(huì )工作。
4、要想讓定時(shí)器工作,就是加1,從圖上看有兩種方式,第一種方式是那個(gè)開(kāi)關(guān)打到上邊的箭頭,就是C/T = 0的時(shí)候,一個(gè)機器周期TL就會(huì )加1一次,當開(kāi)關(guān)打到下邊的箭頭,即C/T =1的時(shí)候,T0引腳即P3.4引腳來(lái)一個(gè)脈沖,TL就加1一次,這也就是計數器功能。
INT0引腳是P3.2,INT1引腳是P3.3,T0引腳是P3.4,T1引腳是P3.5。
三、定時(shí)器程序應用
了解了定時(shí)器相關(guān)的寄存器,那么我們下面就來(lái)做一個(gè)定時(shí)器的程序,鞏固一下我們學(xué)到的內容。我們這節課的程序先使用定時(shí)器0,在使用定時(shí)器的時(shí)候,需要以下幾個(gè)步驟:
第一步:設置特殊功能寄存器TMOD,配置好工作模式;
第二步:設置計數寄存器TH0和TL0的初值;
第三步:設置TCON,通過(guò)打開(kāi)TR0位來(lái)讓定時(shí)器開(kāi)始計數。
第四步:判斷TCON寄存器的TF0位,監測定時(shí)器溢出情況。
寫(xiě)程序之前,我們要先來(lái)學(xué)會(huì )計算如何用定時(shí)器定時(shí)時(shí)間。我們以晶振是11.0592M為例講解,時(shí)鐘周期就是1/11059200,機器周期就是12/11059200,我們假如要定時(shí)20ms,就是0.02秒,要經(jīng)過(guò)x個(gè)機器周期得到0.02秒,我們來(lái)算一下x*12/11059200=0.02,得到x= 18432。那么我們現在16位的定時(shí)器溢出值是65536,我們可以這樣,先給TH0和TL0一個(gè)初值,讓他們經(jīng)過(guò)18432個(gè)機器周期后剛好溢出,溢出后我們可以通過(guò)檢測TF0位得知,就剛好是0.02秒。這個(gè)初值y = 65536 - 18432 = 47104,轉成16進(jìn)制就是0xB800,那么就是TH0 = 0xB8,TL0 = 0x00。
那0.02秒我們已經(jīng)定時(shí)出來(lái)了,細心的同學(xué)會(huì )發(fā)現,我們如果初值直接給一個(gè)0x0000,一直到65536溢出,定時(shí)器定時(shí)值最大也就是71ms左右,那么我們想定時(shí)更長(cháng)時(shí)間怎么辦呢?用你小學(xué)學(xué)過(guò)的邏輯,倍數關(guān)系就可以解決此問(wèn)題。
那好了,我們下面就用程序來(lái)實(shí)現以下這個(gè)功能。
#include //包含寄存器的庫文件
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; //設置定時(shí)器0為模式1
TH0 = 0xB8;
TL0 = 0x00; //定時(shí)值初值
TR0 = 1; //打開(kāi)定時(shí)器0
while(1)
{
if(1 == TF0) //判斷定時(shí)器0是否溢出
{
TF0 = 0;
TH0 = 0xB8; //一旦溢出后,重新賦值
TL0 = 0x00;
counter++;
if(50 == counter) //判斷定時(shí)器0溢出是否達到50次
{
counter = 0; //counter清0,重新計數
LED = !LED; //LED取反操作,0-->1,1-->0
}
}
}
}
程序都有注釋?zhuān)浑y理解,這里要解釋一個(gè)地方,就是兩次if判斷,細心的同學(xué)會(huì )發(fā)現,if(1 == TF0)這句,我把1寫(xiě)前邊,這個(gè)地方我推薦新手按照我這樣來(lái)寫(xiě),因為如果我們寫(xiě)if(TF0 == 1),作為新手來(lái)說(shuō),不小心丟掉一個(gè)’=’號后,寫(xiě)成if(TF0 = 1),這樣實(shí)際上在語(yǔ)法上是可以通過(guò)的,我們用的Keil4還會(huì )出一個(gè)警告說(shuō)明一下,Keil以前的版本以及一些其他軟件,可能根本不會(huì )出任何錯誤或者警告提示,但是這樣產(chǎn)生的Hex文件下載到單片機里邊,程序就錯了,大家可以改改試試看。
本程序實(shí)現的結果是小燈點(diǎn)亮持續一秒,熄滅持續一秒,也就是以0.5HZ的頻率進(jìn)行閃爍。
評論