<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 單片機頻率測量原理

          單片機頻率測量原理

          作者: 時間:2016-11-13 來源:網(wǎng)絡(luò) 收藏
          單片機應(yīng)用系統(tǒng)中,經(jīng)常要對一個連續(xù)的脈沖波頻率進行測量。在實際應(yīng)用中,對于轉(zhuǎn)速,位移、速度、流量等物理量的測量,一般也是由傳感器轉(zhuǎn)換成脈沖電信號,采用測量頻率的手段實現(xiàn)。

          使用單片機測量頻率或周期,通常是利用單片機的定時計數(shù)器來完成的,測量的基本方法和原理有兩種:

          本文引用地址:http://www.ex-cimer.com/article/201611/316136.htm

          測頻法:在限定的時間內(nèi)(如1秒鐘)檢測脈沖的個數(shù)。

          測周法:測試限定的脈沖個數(shù)之間的時間。

          這兩種方法盡管原理是相同的,但在實際使用時,需要根據(jù)待測頻率的范圍、系統(tǒng)的時鐘周期、計數(shù)器的長度、以及所要求的測量精度等因素進行全面和具體的考慮,尋找和設(shè)計出適合具體要求的測量方法。

          在具體頻率的測量中,需要考慮和注意的因素有以下幾點。

          ü 系統(tǒng)的時鐘。首先測量頻率的系統(tǒng)時鐘本身精度要高,因為不管是限定測量時間還是測量限定脈沖個數(shù)的周期,其基本的時間基準是系統(tǒng)本身時鐘產(chǎn)生的。其次是系統(tǒng)時鐘的頻率值,因為系統(tǒng)時鐘頻率越高,能夠?qū)崿F(xiàn)頻率測量的精度也越高。因此使用AVR測量頻率時,建議使用由外部晶體組成的系統(tǒng)的振蕩電路,不使用其內(nèi)部的RC振蕩源,同時盡量使用頻率比較高的系統(tǒng)時鐘。

          ü 所使用定時計數(shù)器的位數(shù)。測量頻率要使用定時計數(shù)器,定時計數(shù)器的位數(shù)越長,可以產(chǎn)生的限定時間越長,或在限定時間里記錄的脈沖個數(shù)越多,因此也提高了頻率測量的精度。所以對頻率測量精度有一定要求時,盡量采用16位的定時計數(shù)器。

          ü 被測頻率的范圍。頻率測量需要根據(jù)被測頻率的范圍選擇測量的方式。當被測頻率的范圍比較低時,最好采用測周期的方法測量頻率。而被測頻率比較高時,使用測頻法比較合適。需要注意的是,被測頻率的最高值一般不能超過測頻MCU系統(tǒng)時鐘頻率的1/2,因為當被測頻率高于MCU時鐘1/2后,MCU往往不能正確檢測被測脈沖的電平變化了。

          除了以上三個因素外,還要考慮頻率測量的頻度(每秒內(nèi)測量的次數(shù)),如何與系統(tǒng)中其它任務(wù)處理之間的協(xié)調(diào)工作等。頻率測量精度要求高時,還應(yīng)該考慮其它中斷以及中斷響應(yīng)時間的影響,甚至需要在軟件中考慮采用多次測量取平均的算法等。

          采用測頻法的頻率計設(shè)計與實現(xiàn)

          1) 硬件電路

          硬件電路的顯示部分,PA口為8個LED數(shù)碼管的段輸出,PC口控制8個LED數(shù)碼管的位掃描。使用T/C0對被測信號輸入的脈沖個數(shù)進行計數(shù),被測頻率信號由PB0(T0)輸入。

          2) 軟件設(shè)計

          我們首先給出系統(tǒng)程序,然后做必要的說明。

          /*********************************************

          File name : demo_11_1.c

          Chip type : ATmega16

          Program type : Application

          Clock frequency : 4.000000 MHz

          Memory model : Small

          External SRAM size : 0

          Data Stack size : 256

          *********************************************/

          #include

          flash char led_7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

          flash char position[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

          char dis_buff[8]; // 顯示緩沖區(qū),存放要顯示的8個字符的段碼值

          char posit;

          bit time_1ms_ok,display_ok=0;

          char time0_old,time0_new,freq_time;

          unsigned int freq;

          void display(void) // 8位LED數(shù)碼管動態(tài)掃描函數(shù)

          {

          PORTC = 0xff;

          PORTA = led_7[dis_buff[posit]];

          if (posit==5) PORTA = PORTA | 0x80;

          PORTC = position[posit];

          if (++posit >=8 ) posit = 0;

          }

          // Timer 2 output compare interrupt service routine

          interrupt [TIM2_COMP] void timer2_comp_isr(void)

          {

          time0_new = TCNT0; // 1ms到,記錄當前T/C0的計數(shù)值

          time_1ms_ok = 1;

          display_ok = ~display_ok;

          if (display_ok) display();

          }

          void freq_to_disbuff(void) // 將頻率值轉(zhuǎn)化為BCD碼并送入顯示緩沖區(qū)

          {

          char i,j=7;

          for (i=0;i<=4;i++)

          {

          dis_buff[j-i] = freq % 10;

          freq = freq / 10;

          }

          dis_buff[2] = freq;

          }

          void main(void)

          {

          char i;

          DDRA=0xFF; // LED數(shù)碼管驅(qū)動

          DDRC=0xFF;

          // T/C0初始化,外部計數(shù)方式

          TCCR0=0x06; // 外部T0腳下降沿觸發(fā)計數(shù),普通模式

          TCNT0=0x00;

          OCR0=0x00;

          // T/C2初始化

          TCCR2=0x0B; // 內(nèi)部時鐘,32分頻(4M/32=125KHz),CTC模式

          TCNT2=0x00;

          OCR2=0x7C; // OCR2 = 0x7C(124),(124+1)/125=1ms

          TIMSK=0x80; // 允許T/C2比較匹配中斷

          for (i=0;i<=7;i++) dis_buff[i] = 0;

          time0_old = 0;

          #asm("sei") // 開放全局中斷

          while (1)

          {

          if (time_1ms_ok)

          { // 累計T/C0的計數(shù)值

          if (time0_new >= time0_old) freq = freq + (time0_new - time0_old);

          else freq = freq + (256 - time0_old + time0_new);

          time0_old = time0_new;

          if (++freq_time >= 100)

          {

          freq_time = 0; // 100ms到,

          freq_to_disbuff(); // 將100ms內(nèi)的脈沖計數(shù)值送顯示

          freq = 0;

          }

          time_1ms_ok = 0;

          }

          };

          }

          程序中LED掃描形式函數(shù)desplay(),以及脈沖計數(shù)值轉(zhuǎn)換成BCD碼并送顯示緩沖區(qū)函數(shù)freq_to_disbuff()比較簡單,請讀者自己分析。

          在該程序中,使用了兩個定時計數(shù)器。T/C0工作在計數(shù)器方式,對外部T0引腳輸入的脈沖信號計數(shù)(下降沿觸發(fā))。T/C2工作在CTC方式,每隔1ms中斷一次,該定時時間即作為LED的顯示掃描,同時也是限定時間的基時。每一次T/C2的中斷中,都首先記錄下T/C0寄存器TCNT0當前的計數(shù)值,因此前后兩次TCNT0的差值(time0_new – time0_old)或(256 - time0_old + time0_new)就是1ms時間內(nèi)T0腳輸入的脈沖個數(shù)。為了提高測量精度,程序?qū)?00個1ms的脈沖個數(shù)進行了累計(在變量freq中),即已知限定的時間為100ms。

          讀者還應(yīng)該注意頻率的連續(xù)測量與LED掃描、BCD碼轉(zhuǎn)換之間的協(xié)調(diào)問題。T/C2中斷間隔為1ms,因此在1ms時間內(nèi),程序必須將脈沖個數(shù)進行的累計、BCD碼轉(zhuǎn)換和送入顯示緩沖區(qū),以及LED的掃描工作完成掉,否則就會影響到下一次中斷到來后的處理。

          在本實例的T/C2中斷中,使用了display_ok標志,將LED掃描分配在奇數(shù)ms(1、3、5、7、……),而將1ms的TCNT0差值計算、累積和轉(zhuǎn)換等處理放在主程序中完成。另外由于計算量大的BCD碼轉(zhuǎn)換是在偶數(shù)ms(100ms)處理,所以程序中LED的掃描處理和BCD碼轉(zhuǎn)換處理不會同時進行(不會在兩次中斷間隔的1ms內(nèi)同時處理LED掃描和BCD碼轉(zhuǎn)換),這就保證了在下一次中斷到達時,前一次的處理已經(jīng)全部完成,使頻率的連續(xù)測量不受影響。

          該實例程序的性能和指標為(假定系統(tǒng)時鐘沒有誤差 = 4MHz):

          ü 頻率測量絕對誤差:±10Hz。由于限定的時間為100ms,而且T/C0的計數(shù)值有±1的誤差,換算成頻率為±10Hz。

          ü 被測最高頻率值:255KHz。由于T/C0的長度8位,所以在1ms中,TO輸入的脈沖個數(shù)應(yīng)小于255個,大于255后造成T/C0的自動清另,丟失脈沖個數(shù)。

          ü 測量頻度:10次/秒。限定的時間為100ms,連續(xù)測量,所以為10次/秒。

          ü 使用資源:兩個定時器,一個中斷。



          關(guān)鍵詞: 單片機頻率測

          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();