<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 單片機定時(shí)器中斷原理和C語(yǔ)言代碼詳解

單片機定時(shí)器中斷原理和C語(yǔ)言代碼詳解

作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò ) 收藏
我之前都是用ARM7,單片機基本不會(huì )。但一個(gè)項目要用到51,所以克了一下51還是有點(diǎn)模糊,今天調了這個(gè)代碼之后,對51定時(shí)器中斷有些心得,拿來(lái)和大家共享。廢話(huà)不說(shuō)了,上代碼。

#define _1231_C_
#include "reg51.h"
#include "1231.h"


//sbit OE=P2^3;

unsigned int SystemTime;


void timer0(void) interrupt 1 using 3 //中斷部分代碼,見(jiàn)下文的釋疑
{

TH0 = 0xdb;
TL0 = 0xff;
// TF0 = 0;

SystemTime++;
}


void main()
{

TMOD &= 0xF0;
TMOD |= 0x01; //TMOD的值表示定時(shí)器工作方式選擇

TH0 = 0xdb; //寫(xiě)入初始值,初始值可以決定定時(shí)多久
TL0 = 0xff;
//根據下文的木桶比喻的話(huà),如果TH0 = 0x00;TL0 = 0x00;則表示從桶底開(kāi)始裝水。
//TH0 = 0xdb;TL0 = 0xff;可以這樣子理解相當于木桶里已經(jīng)有部分液鉛在里面,
//TH0和TL0這個(gè)兩個(gè)值表示木桶里液鉛的高度,即此時(shí)桶里只能從液鉛的高度以上開(kāi)始裝水,
//TH0 = 0xff;TL0 = 0xff;即表示桶的最高位置.

TF0 = 0; //計數到時(shí)TF0為1,即當TH0 = 0xff;TL0 = 0xff;再運行一步TF0 = 1;
TR0 = 1; //開(kāi)始計數,從這時(shí)起,每運行一步TH0和TL0都會(huì )增加,直到TH0 = 0xff;TL0 = 0xff;
//相當于開(kāi)水龍頭,如TR0=0則TH0和TL0不變

ET0 = 1; //允許定時(shí)器0中斷
EA=1; //開(kāi)總中斷

//下面是個(gè)死循環(huán),程序里每運行一步TH0和TL0都會(huì )增加,當增加到TH0 = 0xff;TL0 = 0xff;
//單片機會(huì )從死循環(huán)里退出,去執行中斷部分的代碼,即開(kāi)始運行void timer0(void) interrupt 1 using 3{}
//運行完中斷部分的代碼后,接著(zhù)繼續執行死循環(huán)里的代碼。
//注意:當TH0 = 0xff;TL0 = 0xff;再運行,TF0并沒(méi)有從0變?yōu)?,個(gè)人猜測TF0=1;時(shí)觸發(fā)了中斷,并重新被置零。
//如把ET0 = 1;和EA=1;注釋掉,當TH0 = 0xff;TL0 = 0xff;再運行,TF0會(huì )變?yōu)?,此時(shí)不會(huì )再執行中斷部分代碼。

while(1)
{
if ((SystemTime%100)<50) //SystemTime除以100,余數小于50為真
{
//這兩行不用管,就當做是功能1
P0=0xf1;
P2=0xf0;

}
else
{
//這兩行不用管,就當做是功能2
P0=0x00;
P2=0xf0;

}


};



}


釋疑:void Timer0() interrupt 1 using 1



Timer0 是函數名,隨便取的

interrupt xx using y

跟在interrupt 后面的xx 值得是中斷號,就是說(shuō)這個(gè)函數對應第幾個(gè)中斷端口,一般在51中

0 外部中斷0

1 定時(shí)器0

2 外部中斷1

3 定時(shí)器1

4 串行中斷

實(shí)際上編譯的時(shí)候就是把你這個(gè)函數的入口地址方到這個(gè)對應中斷的跳轉地址

using y 這個(gè)y是說(shuō)這個(gè)中斷函數使用的那個(gè)寄存器組,51里面一般有4組 r0 -- r7寄存器,一共有32個(gè),如果你的終端函數和別的程序用的不是同一個(gè)寄存器組則進(jìn)入中斷的時(shí)候就不會(huì )將寄存器組壓入堆棧返回時(shí)也不會(huì )談出來(lái)節省代碼和時(shí)間

初始值算法:定時(shí)器是當總數達到FFFFH后產(chǎn)生中斷吧!那你要讓它計數10000,是不是用FFFF(16進(jìn)制)減去10000(十進(jìn)制)的數當計數初值???TH0=-(10000/256); TL0=-(10000%256)跟FFFF(16進(jìn)制)減去10000(十進(jìn)制)的數是一樣的。從TH0=-(10000/256); TL0=-(10000%256)開(kāi)始計數,計數到10000剛好滿(mǎn)。跟用FFFF(16進(jìn)制)減去10000(十進(jìn)制)的數一樣?。?!寫(xiě)起來(lái)更簡(jiǎn)單,不用算?。?!
看看原碼、補碼就知道。正數的補碼是對應的二進(jìn)制數,符號位為零,負數的補碼是它的絕對值對應的二進(jìn)制數按位取反再加一,符號位為一。無(wú)符號數不考慮符號,那么這個(gè)結果就跟用FFFF減去它的絕對值一樣


我們學(xué)習了用指令延時(shí)閃燈,但是用指令方式閃燈有cpu不能做其他工作的缺點(diǎn)。
這一課,我們將學(xué)習如何使用定時(shí)器方式使燈閃爍。
中斷的理解。
這里將涉及到單片機中斷的應用,在cpu的一步步按照指令運行的過(guò)程中(主程序),可能會(huì )有其它的更緊急的需要做的事情(中斷服務(wù)程序),需要cpu暫時(shí)停止當前的程序(主程序),做完了(中斷服務(wù)程序)之后,又可以繼續去運行先前的程序(主程序)。就像你正在吃飯,一邊又在給水桶里放水,吃著(zhù)吃著(zhù),水滿(mǎn)了,你就得趕快去把水龍頭關(guān)掉或者換一個(gè)空的水桶,再回來(lái)吃飯。
單片機的定時(shí)器就像是一個(gè)水桶,你讓它啟動(dòng)了,也就是水龍頭打開(kāi)了;開(kāi)始裝水了;定時(shí)在每個(gè)機器周期不斷自動(dòng)加1,最后溢出了;水桶的水不斷增加,最也就滿(mǎn)出來(lái)了;定時(shí)器溢出時(shí),你就要去做處理了;水桶的水滿(mǎn)了,你也應該處理一下了;處理完后,單片機又可以回到剛剛開(kāi)停止的地方繼續運行;水桶處理了,先前你在做什么也可以繼續去做什么了。
單片機的主程序是從0x0000開(kāi)始運行的,單片機服務(wù)程序從哪里開(kāi)始運行呢?在51里,有多個(gè)中斷服務(wù)程序入口,0號入口是外中斷0,地址在0x0003;1號入口是定時(shí)器0,在 0x000B;2號入口是外中斷1;地址在0x0013,3號入口是定時(shí)器2;地址在0x001B,等等。當中斷發(fā)生時(shí),程序就記下當前運行的位置,跳到對應的中斷入口去運行中斷服務(wù)程序,運行完之后,又跳回到原來(lái)的位置繼續運行。
在C51中,你不用理會(huì )中斷服務(wù)程序放在哪里,會(huì )怎么跳轉。你只要把某個(gè)函數標識為幾號中斷服務(wù)函數就可以了。在發(fā)生了對應的中斷時(shí),就會(huì )自動(dòng)的運行這個(gè)函數。
請看一下相關(guān)的51的硬件的書(shū),對定時(shí)器工作的寄存器設置做進(jìn)一步的了解。也可以做完試驗再了解,因為例程中都已經(jīng)為您設置好了。
請看程序,主程序里的循環(huán)里是個(gè)死循環(huán),什么也沒(méi)有做,在實(shí)際應用中這里是放的主程序。
在定時(shí)器服務(wù)函數里,需要重新置入定時(shí)器的值,這樣才能保證每次溢出時(shí),都是你指定的時(shí)間。這里置入的是0x0006,還需要走 0x10000-0x0006個(gè)機器周期才溢出。換成10進(jìn)制也就是每65530個(gè)機器周期中斷一次。我們仿真的晶振是22118400HZ,每12個(gè)時(shí)鐘一個(gè)機器周期。65530×12/22118400=0.036秒。也就是差不多28HZ的閃爍頻率。
因為51的定時(shí)器最大只有0xffff,溢出的速度很快,無(wú)法做出更久的閃爍頻率來(lái),這一課就先觀(guān)察一下這個(gè)28HZ左右頻率。在下一課我們會(huì )用靜態(tài)變量的辦法,做一個(gè)長(cháng)達1秒鐘的LED閃爍頻率。
另外,由于51從中斷發(fā)生到進(jìn)入中斷的時(shí)間不定,是3至8個(gè)機器周期,我們在進(jìn)入了中斷后才重新置新的定時(shí)器初始值,這樣就會(huì )存在定時(shí)誤差。也就是不是精確定時(shí),如果要精確定時(shí),需要使用定時(shí)器自動(dòng)裝載方式,也就是在定時(shí)器溢出的同時(shí),硬件邏輯就自動(dòng)把定時(shí)器初始值裝載進(jìn)去了,而不是在中斷服務(wù)程序里賦初始值,這樣就可以實(shí)現精確定時(shí),誤差只出現晶振的頻率上。這是下一顆的內容。
現在請仔細研究一下程序,并編譯,進(jìn)入仿真,全速運行,觀(guān)察運行結果。我們可以看到P10上的LED在快速閃爍。
順便,也請再練習一下停止,單步,斷點(diǎn)等等的調試方法。
一個(gè)特殊的地方,使用DX516在單步時(shí)運行時(shí),可能無(wú)法進(jìn)入到中斷服務(wù)函數中。這是因為中斷函數可能在單步處理的瞬間已經(jīng)運行過(guò)去了。如果要單步調試中斷服務(wù)函數,請在中斷服務(wù)函數內設置斷點(diǎn),再點(diǎn)全速。稍后就會(huì )停止在斷點(diǎn)上,就可以繼續單步運行了。


評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>