這里說一說定時器的理解學習思路。 定時器其實就是個計數器,我們用得最多的是用于計時,計時這個東西我們應該都明白是個什么東西,手機里的秒表就屬于這個東西。手機上是怎么用的?一,調出手機的秒表功能,二歸零,三按下開始,四盯著看看到沒到我們預定的時間值。 單片機里是一樣的流程,先將其設置成計時功能,然后呃不是歸零而是設置起始值(初始值),三給個信號讓其開始,四不停地查詢看其是否計數滿值了。這樣一說,計時器是不是在你眼中變得很低級? 知道了計時器的工作原理,編程時具體怎么做?查芯片說明書啊,管它什么芯片,都一個查字:計時器功能設置在哪個單元,找地址嘛;初始值要放在哪個單元,啟動信號在哪個單元,計滿信號(溢出信號)在哪個單元,還是個查字。查到之后,就是修改,怎么修改,還是查說明書啊。 說說為什么要弄個初始值,對于十六位的計時器來說,計時最大值就是65535,再加1就漫出了(溢出)。51單片機的設計上,計數方式是加加加,也就是計數單元中的值是增加方式,如果我們想計數100,從0開始也不是不行,但你要去不斷地判斷其值是否到了99,這個也不是不行,但有更好的方法,那就是從65436開始,計到溢出,而計數器本身設計了一個功能,就是溢出后就給出一個溢出信號,這個信號存在某一個單元之中(稱之為溢出標志,51單片機存在某個單元的某一位上,稱之為溢出標志位),程序運行中只需要盯著這個標志位的值就行了,用不著盯計數值。 談點芯片設計人員的思路,上面說的是計數值加加加,那采用計數值減減減的方式可以不可以實現呢?這個問題并不復雜,我在這里就不羅嗦了。 可以說,這個溢出標志的設計,是很好的設計,定時器的中斷功能,也是在這個基礎上弄出來的。 有了以上的知識,那我們在應用定時器進行編程時,思路也就很清楚了,首先使用前別忘了標志位應該是零啊,啟動位當然也要是零,然后把初始值送進去,然后設置(也可以說是調出)其計時功能(十六位的或八位的,按你的需要),然后把啟動位設置成開始(啟動),然后不停查詢標志位的值。哦還有一點,單片機的定時器不止一個,以上這些動作,只對你所選擇的那個定時器進行編程。再有一點,計時完成之后,啟動位、溢出標志位等是否需要人工處理,這個要看說明書。 吐槽一下:現有的教材都是告訴你有這些特殊功能寄存器、如何設置這些寄存器,卻沒怎么講解為什么機器中存在這些寄存器、為什么需要設置這些項目,這樣的結果,自然是讓人不容易理解掌握,不能理解的結果,就只能是死記硬背,反正本人特煩死記硬背,沒法,記性比別人差,于是只能逼著自己去理解原理,理解了原理,編程就是心中長了竹子。 好了,下面我們就查表,首先是計時功能設置的單元,教材中稱之為定時器工作方式寄存器,俗名TMOD,設計在片內數據存儲單元中,歸于特殊功能寄存器,對這類單元只能直接尋址,不能間接尋址,該單元沒有設計位尋址功能,其地址編號為89H,這個單元控制兩個定時器的工作模式(標準的51機有兩個定時器),高四位控制定時器1,低四位控制定時器0。這四個位的功能在一般的教材上都有講解,反正如果你想使用十六位計時功能時,將四位設成0001就行了。因為不能位尋址,那一次就得送入一整個字節,所以如果你若讓定時器1閑著而用定時器0,那就得把00000001B送入89H單元中,可以用MOV命令將00000001B作為立即數送入89H中(當然你也可以將其先存于某個單元之中再送入),前面說了對于特殊功能寄存器89H這個單元只能直接尋址,那么這個單元的地址就必須直接寫在這條語句中,所以這條命令是這樣寫的:MOV 89H,#00000001B,當然,89H這個單元你可以不用數據地址,而是用其俗名來代替,這個俗名,程序編輯器中已經有了一個,就是“TMOD”,于是,這條命令就可以這樣寫:MOV TMOD,#00000001B。也當然,如果你不喜歡TMOD這個俗名,你自己取一個自己喜歡自己好記的名字也行。 再就是計數數據單元了,它是十六位,就是兩個字節,51機是每個單元里面存的是一個字節的數據,那十六位就得兩個字節,就得占用兩個單元;51機每個單元都有一個地址編號,那兩個單元就得兩個地址編號。查說明書,這兩個計數單元也屬于“特殊功能寄存器”的范疇,不可位尋址,只能直接尋址,所以可以同上面一樣的格式編寫語句將初始值送入。定時器0的高字節地址編號為8CH,俗名TH0;低字節為8AH,俗名TL0。 再接下來就是啟動設置,還有溢出標志,這兩個放在一起講,是因為51機芯片設計中將這兩個放在了同一個單元中,只是在不同的位。查說明書,仍屬于“特殊功能寄存器”,只能直接尋址,可位尋址,單元地址編號88H,俗名TCON,這一個單元控制兩個定時器,其中的第5位(注意,現有教材中的規定是最低位編號為第0位,最高位編號為第7位)是定時器0的啟動設置位,這一位的地址編號為8CH,俗名TR0;第6位是定時器0的溢出標志位,這一位的地址編號為8DH,俗名TF0。所以,對這兩個位的操作,我們既可以一次送入一個字節到TCON中去,也可以直接操作位。位的操作蠻簡單,在51機中,所有的位尋址是只能直接尋址(即在任何時候編寫程序時,都只能將其地址直接寫在語句中),不具有任何其它的尋址方式。對位的操作51機設計的動作比較少,常用的有兩種動作:清零和置位(置位就是置1),51機對位的清零操作碼是C2H,匯編助記符CLR;置位的操作碼是D3H,匯編助記符為SETB。前面說了,寫程序時,只能直接在語句中寫它的位地址,所以,編寫時,在操作碼后面直接寫上其位地址就行了,即SETB 8CH(SETB TR0)啟動定時器0,CLR 8DH(SETB TF0)清零定時器0的溢出標志。 解釋一下51機芯片的位尋址設計。51機的片內數據存儲單元中,有一部分單元的位,是統一編有地址的,這個地址是8位地址,編號從0開始,最大255,所以其最多只能對256個位給予地址編號(即最多只有32個單元能有位尋址功能),有了這個地址編號,我們就可以依據這個地址編號,直接找到這個位并進行操作。接下來我們就有了一個疑惑,片內數據存儲單元的編號也是從0到255,那么機器是怎么區分這兩者而不會弄混的?答案就在操作碼上,51機的操作碼本身就暗含了接下來的操作的對象是單元還是位,可以這樣理解:對單元進行操作的操作碼打開的是一道門,門后通向單元;對位進行操作的操作碼打開的是另一道門,門后通向位。另外說一句,其它種類的單片機不一定是這樣設計的,如stm32的設計,它是統一編號,不管是單元還是位,它們的地址全在0到4G的編號之內。 寫得好辛苦啊,沒想到會寫出這么多。定時器的自動重載和中斷,就不寫了,有了以上的知識,自己應該可以推理出來吧?
|