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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > AVR定時/計數(shù)器應用設計

          AVR定時/計數(shù)器應用設計

          作者: 時間:2016-11-11 來源:網(wǎng)絡 收藏
          定時/計數(shù)器(Timer/counter)是單片機芯片中最基本的外圍接口,它的用途非常廣泛,常用于測量時間、速度、頻率、脈寬、提供定時脈沖信號等。相對于一般8位單片機而言,AVR不僅配備了更多的定時/計數(shù)器接口,而且還是增強型的,功能非常強大。ATmega128一共配置了2個8位和2個16位,共4個定時/計數(shù)器,本小節(jié)重點對它的一些增強功能的應用做基本的介紹。

          5.9.1預分頻器
          定時/計數(shù)器最基本的功能就是對脈沖信號計數(shù),當計數(shù)器計滿后(8位為255,16位為65535),再來一個脈沖它就翻轉到0,并產(chǎn)生中斷信號。同其他單片機類似,AVR的定時/計數(shù)器的計數(shù)脈沖可以來自外部的引腳,也可以由從內(nèi)部系統(tǒng)時鐘獲得;但AVR的定時/計數(shù)器在內(nèi)部系統(tǒng)時鐘和計數(shù)單元之間增加了一個預分頻器,利用預分頻器,定時/計數(shù)器可以從內(nèi)部系統(tǒng)時鐘獲得不同頻率的信號。表5-1為系統(tǒng)時鐘為4MHz使用定時/計數(shù)器0的最高計時精度和時寬范圍。

          表5-1T/C0計時精度和時寬(系統(tǒng)時鐘4MHz)
          分頻系數(shù)計時頻率最高計時精度(TCNT0=255)最寬時寬(TCNT0=0)
          14MHz0.25us64us
          8500KHz2us512us
          32125KHz8us2.048ms
          6462.5KHz16us4.096ms
          12831.25KHz32us8.192ms
          25615.625KHz64us16.384ms
          10243906.25Hz256us65.536ms

          從表中看出,在系統(tǒng)時鐘為4MHz時,8位的T/C0最高計時精度為0.25us,最長的時寬可達到65.536ms。而使用16位的定時/計數(shù)器時,不需要輔助的軟件計數(shù)器,就可以非常方便的設計一個時間長達16.777216秒(精度為256us)的定時器,這對于其它的8位單片機是做不到的。
          AVR單片機的每一個定時/計數(shù)器都配備獨立的、多達10位的預分頻器,由軟件設定分頻系數(shù),與8/16位定時/計數(shù)器配合,可以提供多種檔次的定時時間。使用時可選取最接近的定時檔次,即選8/16位定時/計數(shù)器與分頻系數(shù)的最優(yōu)組合,減少了定時誤差。所以,AVR定時/計數(shù)器的顯著特點之一是:高精度和寬時范圍,使得用戶應用起來更加靈活和方便。此外,AVR的USART、SPI、I2C、WDT等都不占用這些定時/計數(shù)器。

          5.9.2輸入捕捉功能
          ATmega128的兩個16位定時/計數(shù)器(T/C1、T/C3)具有輸入捕捉功能,它是AVR定時/計數(shù)器的又一個顯著的特點。其基本作用是當一個事件發(fā)生時,立即將定時/計數(shù)器的值鎖定在輸入捕捉寄存器中(定時/計數(shù)器保持繼續(xù)運行)。利用輸入捕捉功能,可以對一個事件從發(fā)生到結束的時間進行更加精確,如下面的示例中精確測量一個脈沖的寬度。
          測量一個脈沖的寬度,就是測量脈沖上升沿到下降之間的時間。不使用輸入捕捉功能,一般情況往往需要使用兩個外圍部件才能完成和實現(xiàn)。如使用1個定時/計數(shù)器加1個外部中斷(或模擬比較器):定時/計數(shù)器用于計時;而外部中斷方式設置成電平變化觸發(fā)方式,用于檢測脈沖的上升和下降沿。當外部中斷輸入電平由低變高,觸發(fā)中斷,讀取時間1;等到輸入電平由高變低時,再次觸發(fā)中斷,讀取時間2;兩次時間差既為脈沖寬度。這種實現(xiàn)方式不僅多占用了一個單片機的內(nèi)部資源,而且精度也受到中斷響應時間的限制。因為一旦中斷發(fā)生,MCU響應中斷需要時間,在中斷中可能要進行適當?shù)闹袛喱F(xiàn)場保護,才能讀取時間值。而此時的時間值比中斷發(fā)生的時間已經(jīng)滯后了。
          而使用ATmega128的1個定時/計數(shù)器,再配合其輸入捕捉功能來測量脈沖的寬度就非常方便,下面是實現(xiàn)的程序示例。

          #include

          #defineICP1 PIND.4 //脈沖輸入由ICP1(Pind.4)輸入

          unsignedcharov_counter;
          unsignedintrising_edge,falling_edge;
          unsignedlongpulse_clocks;

          interrupt[TIM1_OVF]voidtimer1_ovf_isr(void) //T/C1溢出中斷
          {
          ov_counter++; //記錄溢出次數(shù)
          }

          interrupt[TIM1_CAPT]voidtimer1_capt_isr(void) //T/C1捕捉中斷
          {
          if(ICP1)
          { //上升沿中斷
          rising_edge=ICR1; //記錄上升沿開始時間
          TCCR1B=TCCR1B&0xBF; //設置T/C1為下降沿觸發(fā)捕捉
          ov_counter=0; //清零溢出計數(shù)器
          }
          else
          { //下降沿中斷
          falling_edge=ICR1; //記錄下降沿時間
          TCCR1B=TCCR1B|0x40; //設置T/C1為上升沿觸發(fā)捕捉
          pulse_clocks=(unsignedlong)falling_edge-(unsignedlong)rising_edge
          +(unsignedlong)ov_counter*0x10000/500; //計算脈沖寬度
          }
          }

          voidmain(void)
          {
          TCCR1B=0x42; //初始化T/C1,1/8分頻,上升沿觸發(fā)捕捉
          TIMSK=0x24; //允許T/C1溢出和捕捉中斷
          #asm("sei")

          while(1)
          {………
          };
          }
          這段程序是在CVAVR中實現(xiàn)的。在T/C1的捕捉中斷中,先檢查ICP1的實際狀態(tài),以確定是出現(xiàn)了上升沿還是下降沿信號。如果中斷是由上升沿觸發(fā)的(ICP1為高電平),程序便開始一次脈沖寬度的測量:記錄下上升沿出現(xiàn)的時間,把T/C1的捕捉觸發(fā)方式改為下降沿觸發(fā),并清空溢出計數(shù)器。如果中斷由下降沿觸發(fā)(ICP1為低電平),表示到達脈沖的未端,程序記錄下降沿出現(xiàn)時間,計算出脈沖的寬度,再將T/C1的捕捉觸發(fā)方式改為上升沿觸發(fā),以開始下一次的測量。
          脈沖的實際寬度(毫秒格式)是根據(jù)T/C1的計數(shù)時鐘個數(shù)來計算的。本例中T/C1的計數(shù)時鐘是系統(tǒng)時鐘(4MHz)的8分頻,即500KHz,相應的計數(shù)脈沖寬度為2us。因此計算出從上升沿和下降沿之間總的計數(shù)脈沖個數(shù),除以500個脈沖(為1ms)即得到以毫秒為單位的被測脈沖寬度了。
          可以看到,使用定時/計數(shù)器以及配合它的捕捉功能測量脈沖寬度,不僅節(jié)省系統(tǒng)的硬件資源,編寫程序簡單,而且精度也高,因為讀到的上升沿和下降沿的時間就是其實際發(fā)生的時間。


          關鍵詞: AVR定時計數(shù)

          評論


          技術專區(qū)

          關閉
          看屁屁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); })();