新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STC單片機(jī)timer2捕獲模式測(cè)頻率

STC單片機(jī)timer2捕獲模式測(cè)頻率

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏

在使用STC單片機(jī)測(cè)頻率最常用的方法是在一定時(shí)間內(nèi)計(jì)算脈沖個(gè)數(shù),這種方式一般需要一個(gè)計(jì)數(shù)器和一個(gè)定時(shí)器配合,而且對(duì)低頻信號(hào)也不太準(zhǔn)確,下面我們可以用到timer2捕獲模式通過(guò)測(cè)量?jī)蓚€(gè)下降沿的時(shí)間,來(lái)計(jì)算頻率,這樣做僅使用timer2就好了,而且對(duì)低頻信號(hào)測(cè)量準(zhǔn)確,經(jīng)實(shí)際測(cè)試,在100Hz一下時(shí),精度可達(dá)0.05Hz。

本文引用地址:http://m.butianyuan.cn/article/201611/318508.htm

下面先介紹一下STC51 timer2的捕獲模式:

在捕獲模式中,通過(guò)T2CON中的EXEN2設(shè)置兩個(gè)選項(xiàng),如果EXEN2=0,定時(shí)器作為一個(gè)16位的定時(shí)器或計(jì)數(shù)器,溢出時(shí)置位TF2。該位可用于產(chǎn)生中斷(ET2=1)。如果EXEN2=1,就增加了一個(gè)特性,即外部輸入T2EX(P11)有下降沿時(shí),將timer2中的TH2和TL2當(dāng)前值各自捕獲到RCAP2L和RCAP2H。另外,T2EX的負(fù)跳變使T2CON中的EXF2置位,EXF2也想TF2一樣來(lái)產(chǎn)生中斷(其向量與timer2溢出中斷相同,timer2的中斷服務(wù)通過(guò)查詢TF2和EXF2來(lái)確定引起的中斷事件),若是T2EX中斷,進(jìn)來(lái)后TH2和TL2不會(huì)重新裝載值,會(huì)繼續(xù)以當(dāng)前計(jì)數(shù)往上計(jì)數(shù),除非你確實(shí)想改變TH2和TL2的值,如需要重新計(jì)數(shù)。


下面介紹下程序:

因?yàn)橥獠刻兒鸵绯鼍梢赃M(jìn)入中斷,我們可以利用這一特性來(lái)做對(duì)兩個(gè)脈沖之間的時(shí)間測(cè)量,初始時(shí)設(shè)置TH2和TL2值為0,如果發(fā)生溢出中斷,我們的計(jì)時(shí)變量就自加65536,如果進(jìn)入外部跳變中斷,則我們讀取RCAP2L和RCAP2H的值并與前面的計(jì)時(shí)變量相加即可得到這個(gè)跳變與上一跳變的時(shí)間,注意測(cè)量結(jié)束后要清空計(jì)時(shí)變量以及H2和TL2,方便下一次的重新計(jì)數(shù)。

初始化程序如下:

//定時(shí)器2設(shè)置為捕獲模式,用戶計(jì)算速度void Timer2Init(){char i;EXEN2 = 1;//timer2 outside enableCP_RL2 = 1;//enable capture modeTH2 = TL2 = 0;RCAP2H = RCAP2L = 0;TR2 = 1;//enable timer2ET2=1; //enable timer2 interrupt//將計(jì)時(shí)器存儲(chǔ)區(qū)設(shè)置的很大,也就是頻率先接近0 for(i=0;i<5;i++){plus_length[i] = 6553600;}}
中斷服務(wù)程序如下,在這里keil對(duì)long型的數(shù)據(jù)計(jì)算有點(diǎn)問(wèn)題,需要格外注意:

/** 函 數(shù) 名 :Timer2Int* 函數(shù)功能 :定時(shí)器2中斷函數(shù) , 捕獲模式* 輸    入 :無(wú)* 輸    出 :無(wú) */void Timer2Int() interrupt 5{static volatile long plus_length_temp=0;static char index=0;if(TF2 == 1)//overflow int{TF2 = 0;TH2 = 0;TL2 = 0;RCAP2H = 0;RCAP2L = 0;plus_length_temp = plus_length_temp + 65536;if(plus_length_temp > 6553600) {plus_length[index] = plus_length_temp;//對(duì)最近5個(gè)求平均值index++;if(index == 5) index = 0;plus_length_temp = 0;}}if(EXF2 == 1)//capture int{long temp;TH2 = 0;TL2 = 0;//WTF!!!  clear TH2 and TL2,not TH0 and TH1EXF2 = 0;temp = ((long)(RCAP2H<<8) + RCAP2L) & 0xffff; //奇怪的問(wèn)題,如果不加0xffff,temp高位會(huì)全為ff,從而產(chǎn)生負(fù)數(shù)RCAP2H = 0;RCAP2L = 0;temp = plus_length_temp + temp;//在對(duì)long計(jì)算時(shí)要小心,一步一來(lái)plus_length_temp = temp;plus_length[index] = plus_length_temp;//對(duì)最近5個(gè)求平均值index++;if(index == 5) index = 0;plus_length_temp = 0;//read calc next plus}}

最后就是主函數(shù)部分內(nèi)容,每隔500ms求平均值并打印一次當(dāng)前頻率:

calc_plength = 0;Delayms(500);for(count = 0;count<5;count++){calc_plength += plus_length[count];}calc_plength = calc_plength/5;freq = (float)3990000/calc_plength;//read real frequenceprintf("freq=%frn",freq);

這種方法對(duì)低頻情況下比較有效,但頻率較高時(shí)如達(dá)到上k的頻率,誤差比較大,有明顯的偏高,至于原因,還等待進(jìn)一步研究。


評(píng)論


技術(shù)專區(qū)

關(guān)閉