新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機學習之十四:定時器應用(模式1)

        單片機學習之十四:定時器應用(模式1)

        作者: 時間:2016-11-18 來源:網絡 收藏
        一、實驗現象:

        本文引用地址:http://www.104case.com/article/201611/315889.htm

        開機后程序作如下的燈光變換:第一次led0、led2亮;第二次led1、led3亮;第三次led4、led6亮;第四次led5、led7亮;第五次led0、led2、led4、led6亮;第六次led1、led3、led5、led7亮;第七次8個二極管全亮;第八次8個二極管全滅。然后重頭開始循環。每次狀態轉換間隔時間是50ms。

        二、實驗目的

        掌握內部定時/計數器的作定時功能(模式1)的應用

        三、實驗任務分析:

        看到這個實驗題目,大家可能會說,這個試驗難度不大,我們只要把這幾種燈光對應的輸出存到一個表里面,然后查表就可以啦,燈光轉換之間調用50ms的延時程序即可。 這樣的思路當然可以,但是,如果這樣作,我們就沒有必要寫這個試驗啦。今天,我們要老瓶裝新酒,看看這個50ms的定時時間除了用延時程序完成,還有沒有別的方法。以前的定時,我們常常采用延時程序來完成。其實這種方法不是很完美,由于程序的指令中還包含其他的判斷指令,所以延時程序作定時不是非常精確。由于日常的電子系統常常需要定時和計數的功能,所以MCS-51單片機內部就自帶了兩個16位的寄存器,用來作定時/計數器,我們給它們起了名字,T0、T1。(我們的AT89S52里面有3個定時器,一般的程序兩個就夠啦,我們先介紹這兩個吧。)
        現在就來學習這兩個定時/計數器的用法。這個試驗的實質,就是利用自帶的定時/計數器來產生50ms的定時。
        先來看看這兩個定時/計數器的結構吧,如下圖所示。

        1、定時器的結構:

        從圖上可以看出,定時/計數器的核心是一個加1計數器(注:16位,計數范圍從0000h~ffffh),根據K0開關的不同方向,這個計數器可以對兩個脈沖來源計數,一個是系統的時鐘振蕩器,另外一個是外部的脈沖源。

        2、定時器的工作方式

        當計數器對系統時鐘脈沖計數的時候,由于系統時鐘是一個時間基準,所以脈沖數×脈沖周期就是一段固定時間,因此工作于定時方式;當計數器對外部的脈沖進行計數的時候(也就是對TX端計數,TX端我們用到的時候再解釋吧),就可用于對外部事件計數,工作于計數方式。我們這個試驗要產生50ms的定時,用的是定時功能,在后面的試驗里我們還要作計數功能的試驗。

        我們發現,當k0向上打的時候,工作于定時方式,向下打的時候工作于計數方式。那么k0又是由什么控制的呢?
        K0是一位模擬開關,方向受 這一位的控制,當 =0時,K0向上,工作于定時方式;當 =1時,K0向下,工作于計數方式。(注:數電教材的《AD轉換》一章有模擬開關的原理,大家可以查閱),
        那么, 又是什么呢,它是特殊功能寄存器tmod中的一位。tmod是用來控制定時/計數器的工作方式的,是一個8位的寄存器,它的各位情況如下圖所示:


        (注:tmod是我們又新接觸的一個特殊功能寄存器,和別的特殊功能寄存器一樣,在內部RAM的特殊功能寄存器區。)
        看到了吧, 是tmod寄存器的D2和D6位,所以,如果我們想讓T0工作于定時方式,就應該把D2置0;如果要讓T0工作于計數方式,就應該把D2置1。對T1的控制也是一樣的。
        注意,在這里我要特別說明一點,我們不能用setb指令給tmod的某一位置1,也不能用clr指令給某一位置0。為什么呢?記得我們以前對ie寄存器可以這樣作:setb ea(開中斷),clr ea(關中斷),那么tmod寄存器為什么不行呢?
        這是因為tmod寄存器是不能夠“位尋址”的,也就是說,我們不能單獨的對其中一位進行操作,而必須對整個寄存器進行賦值。而以前我們學過的ie、psw、tcon、acc這幾個特殊功能寄存器卻是可以“位尋址”的。具體的哪些寄存器可以位尋址,而哪些寄存器不行,大家可以參照相關教材,有很詳細的說明。
        再看一下k1,它也是一個模擬開關,當與門輸出是1的時候,開關閉合,啟動計數器;當與門輸出是0的時候,開關打開,計數器停止。至于它如何控制我們稍后介紹。

        3、定時時間的計算

        好啦,知道了怎樣選擇定時還是計數方式,我們就要考慮一下定時時間的計算了。要計算定時時間,我們就要知道計數器的輸入脈沖周期是多少。實際上,計數器是對機器周期計數的,而我們也知道,1個機器周期=12×振蕩周期,所以,計數器的輸入脈沖周期是:12×(1/12MHZ)=1us。

        可見,要產生50ms的定時,只要計數器記50000個脈沖就可以啦。那么,怎樣讓計數器在記入了50000個脈沖后,向單片機發出一個消息,表示定時時間到呢?這就要用到我們以前學習過的概念-中斷啦。我們以前說過,單片機有5個中斷源,兩個是外部中斷 和 ,兩個是T0和T1的溢出中斷,還有一個是串行口中斷。我們以前用過外部中斷 ,這個試驗我們要用到T0的溢出中斷。

        16位的計數器從0開始,記入216=65536個脈沖的時候,會向外面產生溢出,這個溢出把TFX置一,(注:TF0是T0的溢出中斷標志,TF1是T1的溢出中斷標志),從而向CPU申請中斷,在進入中斷處理程序后,由硬件對TFX清0,不需要我們操作。(注:順便說一下TF0和TF1,它是我們以前接觸過的tcon特殊功能寄存器中的兩位,tcon是一個可以“位尋址”的特殊功能寄存器,我們在試驗七中用這個寄存器設置過外部中斷的觸發方式,想不起來的話,回頭看看前面的實驗吧。)

        4、計數初值的計算

        繼續剛才的問題,16位的計數器要記入65536個脈沖才會產生溢出中斷,那么怎樣讓它在記入50000個脈沖后產生中斷呢?這就要用到我們在數電中間學習過的內容啦。我們可以給計數器置一個初值65536-50000=15536,這樣計數器在記入50000個脈沖之后就會產生溢出中斷了。

        那么,怎樣給計數器置初值呢?T0和T1是兩個16位的計數器,我們可以把它們分為高8位THX和低8位TLX。Cpu和T0、T1之間的關系如下圖所示(注:其中,P3.4和P3.5用作第二功能,是工作于計數方式的時候,外部的計數脈沖輸入,也就是定時/計數器結構圖10-1中的TX端。)

        我們以T0為例,要給它置入初值15536,就要對高8位的TH0和低8位的TL0分別置數。15536變換成16進制的數是3CB0(注:轉換方法可以查閱數電教材《進制轉換》一章),所以我們就這樣給T0置初值:mov th0,#3ch ;mov tl0,#0b0h,就可以啦。

        5、計數器的啟動和停止

        在給T0置入初值之后,并且在允許T0溢出中斷(注:由IE寄存器中的ET0控制,詳細說明可見試驗7),和cpu開啟中斷的前提下,我們就要啟動T0開始定時了。我們前面說過T0的啟動和停止是由圖10-1中與門的輸出決定的。當與門輸出是1的時候,T0啟動;當與門輸出是0的時候,T0停止。
        那么什么時候與門輸出是1呢?從圖上可知有兩種情況。
        (1)、當gate=0時,只需要tr0=1,即可啟動T0計數
        (2)、當gate=1,并且tr0=1的時候,還需要int0=1才能啟動T0計數

        在該試驗中,我們用到第一種情況,也就是我們把gate賦值0,然后通過對tr0的置1和置0來啟動和停止計數器。這是一種常用的方式,至于第二種方式,我們以后通過試驗給大家分析它們之間的不同。

        Gate在哪里呢?大家再看看上面給出的tmod寄存器圖,就是d3和d7位。所以我們在對T0初始化的時候,要給d3賦值0。至于d4~d7都和T0沒有關系,可以是任何狀態。
        再說說tr0的問題,它也是tcon寄存器中的一位,它的各位功能如下圖所示,我們把用到的作個簡單介紹。


        1、TF0:T0的溢出中斷,當T0溢出的時候由硬件置位,在進入中斷服務程序后,由硬件清0,不用我們操作;TF1類似。(注:如果我們采用查詢方式,通過查詢TFx的狀態判斷是否到達定時,而不進入中斷服務程序,那就要對這1位用軟件清0啦!可不要忘啦!)
        TR0:當gate=0時,置一啟動T0計數,置0停止T0計數;TR1類似

        好啦,現在基本上分析清楚了,我們來看看主程序和中斷服務程序的流程圖吧。

        四、程序流程圖:

        五、實驗程序
        (注意:在作這個試驗的時候,不要忘了把JMP0跳線置于1、2的位置,選擇二極管顯示單元)
        org 0000h
        ajmp main

        org 000bh ;T0溢出中斷入口地址
        ajmp time0

        org 0020h
        main: clr p1.5
        mov r1,#0ffh
        mov sp,#70h ;設置堆棧
        mov tmod,#01h ;T0初始化,工作于定時方式,詳細解釋見注釋
        mov th0,#3ch ;T0置計數初值
        mov tl0,#0b0h
        setb et0 ;允許T0溢出中斷
        setb ea ;cpu開中斷
        setb tr0 ;啟動T0計數
        ajmp $ ;等待

        time0:inc r1 ;查表求燈光,輸出到p0口,詳細解釋見多位數碼顯示試驗
        mov a,r1
        mov dptr,#tab
        movc a,@a+dptr
        mov p0,a
        cjne a,#0ffh,next
        mov r1,#0ffh
        next: mov th0,#3ch ;由于計數器已經溢出,所以需要重設計數初值
        mov tl0,#0b0h
        reti

        tab: db 0fah,0f5h,0afh,05fh ;按順序存儲燈光的表格
        db 0aah,55h,00h,0ffh
        end

        六、幾點說明
        我們來看看T0初始化的語句mov tmod,#01h,現在我們把tmod的各位功能詳細說明一下。

        (1) d2是定時/計數方式選擇,這里應該把d2置0,選擇T0工作于定時方式
        (2)d3也應該置0,這樣通過控制tr0即可啟動T0
        (3)d1d0(M1M0)用來指明T0的位數,說明如下:
        M1M0=00:13位的計數器;
        M1M0=01:16位計數器;
        M1M0=10:可自動再裝入的8位計數器
        M1M0=11:把定時器0分成兩個8位的計數器,或者關閉定時器1

        (2) 在這個試驗中,由于定時50ms需要16位的計數器,故d1d0=01
        從上面的分析可見,我們給tmod可以賦值:XXXX0001,可以是01h,也可以是0f1h,大家隨便吧。

        現在把這個程序下載到學習板上,看看效果吧。我們發現,燈光變換的速度太快啦,幾乎沒有辦法看清楚,原因很簡單,因為50ms的定時太短了。16位的計數器定時最多能夠達到65.536ms,那么如果我們需要更長時間的定時,比如仍然是剛才的試驗,但是時間要求是1s,該怎么辦呢?

        其實也很簡單,我們設一個計數器,初值是0,每次T0溢出中斷的時候,給這個計數器加一。在主程序里,我們反復檢測這個計數器的值,達到20的時候調用燈光子程序就可以啦。
        下面就是這個定時1s的程序,其中,我們用r2作這個計數器。
        org 0000h
        ajmp main

        org 000bh ;T0溢出中斷入口地址·
        ajmp time0

        org 0020h
        main: clr p1.5
        mov r1,#0ffh
        mov r2,#00h ;給計數器r2賦初值0

        mov sp,#70h ;設置堆棧
        mov tmod,#01h ;設置T0工作方式
        mov th0,#3ch ;T0置計數初值
        mov tl0,#0b0h
        setb et0 ;允許T0溢出中斷
        setb ea ;cpu開中斷
        setb tr0 ;啟動T0開始計數

        wait: cjne r2,#20,wait ;定時時間未到,繼續查詢等待
        acall light ;定時時間到,調用查表求燈光子程序
        ajmp wait

        ;以下是查表求燈光子程序
        light: mov r2,#00h ;計數器重新賦初值

        inc r1 ;查表求燈光,詳細解釋見試驗5“多位數碼顯示”
        mov a,r1
        mov dptr,#tab
        movc a,@a+dptr
        mov p0,a
        cjne a,#0ffh,next
        mov r1,#0ffh
        next: ret ;子程序返回

        ;以下是中斷服務程序
        time0: inc r2 ;計數器加1
        mov th0,#3ch ;重置計數初值
        mov tl0,#0b0h
        reti ;中斷返回

        tab: db 0fah,0f5h,0afh,05fh ;燈光變換表格
        db 0aah,55h,00h,0ffh
        end

        好啦,把這個程序下載到學習板上,就會很清楚的看到燈光的變換方式啦。

        在這個試驗里面,由于我們的定時時間較長,所以采用了16位的計數器,假如定時時間短的話,定時/計數器還可以采用別的工作方式,例如13位,或者8位等。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 高青县| 乐东| 邹平县| 香河县| 凯里市| 乐山市| 上虞市| 垫江县| 中超| 扶余县| 利川市| 浦北县| 新竹县| 昌平区| 嵊泗县| 搜索| 满城县| 东乌珠穆沁旗| 唐河县| 隆安县| 罗田县| 青田县| 宜君县| 鹿邑县| 宝清县| 澳门| 西乡县| 庆城县| 兰州市| 萍乡市| 焉耆| 宁夏| 紫云| 南雄市| 兰州市| 连云港市| 旬阳县| 法库县| 翁源县| 清新县| 聂拉木县|