久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7376|回復: 0
打印 上一主題 下一主題
收起左側

一個關于定時器輸入捕捉測量周期的話題

[復制鏈接]
跳轉到指定樓層
樓主
ID:98618 發表于 2016-2-21 13:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本文作者:Miler Shao

    近日有個工程師網絡留言反映:

    最近在做一個項目關于輸入捕捉的,使用的單片機為STM8S105,用到STM8的輸入捕捉功能。利用庫函數TIME1CH1 捕捉PE0的頻率很準,但此程序基礎上將PE0口的頻率改為由 TIME2產生150HZPWM波形,同樣使用TIME1CH1 捕捉,捕捉到的頻率卻不對。用示波器查看TIME2 產生的PWM很準的。怎么回事呢?

        上面是該工程師的留言,咋看之下,紅色語句貌似就是互相矛盾的表述。呵呵將就下,很多人表述個東西就是任性,讓你猜。      

       順便提醒下,如果在類似論壇或郵件咨詢STMCU的技術問題時,最基本的一條要先把芯片型號說完整,不要說STM8STM32,或者STM32F1STM32F4等。對于STM8一定要說出包括數字在內的前10字符,對于STM32一定要說出包括數字在內的前11字符。這樣人家才能看出該芯片的管腳數和FLASH容量大小,很多問題跟二者息息相關。再就是盡可能把問題描述清楚。

 

    拉回來繼續剛才的話題。他提供的信息除了上面一段話外,再就是系統時鐘配置和定時器初始化代碼以及輸入捕捉測量的函數。他的意思應該是說在利用TIM1CH1捕捉功能對外來脈沖做頻率測量時,當待測信號頻率低到一定程度時就測不準頻率較高時則正常。

 

void TimeCapture(void)

{

  TIM1_ICPolarity = TIM1_ICPOLARITY_FALLING

  TIM1_ICPrescaler = TIM1_ICPSC_DIV8

  。。。【為了節省篇幅,此處省卻部分初始化代碼】

  /* wait a capture on CC1 */

  while((TIM1->SR1 & TIM1_FLAG_CC1) !=TIM1_FLAG_CC1);

  /* Get CCR1 value*/

        ICValue1 = TIM1_GetCapture1();

        TIM1_ClearFlag(TIM1_FLAG_CC1);

 

        /* wait a capture on cc1 */

  while((TIM1->SR1 & TIM1_FLAG_CC1) !=TIM1_FLAG_CC1);

  /* Get CCR1 value*/

        ICValue2 = TIM1_GetCapture1();

        TIM1_ClearFlag(TIM1_FLAG_CC1);

 

  /* Compute  clock frequency */

  ClockFreq = (TIM1_ICPSC_DIV8* TIM1ClockFreq) / (ICValue2 - ICValue1);

}

    從代碼來看,他使用的STM8S TIM1輸入捕捉的例程,下降沿捕捉。結合他的描述和現象分析,代碼配置應該沒啥問題了。我看到他的初始化代碼里使用16M HIS做系統時鐘,供給TIM1的時鐘沒有分頻,即16M。他對輸入捕捉事件做了8分頻,就是上面代碼中的紅色語句。


    他做這個8分頻,意味著每8個下降沿才捕捉1次。150Hz本來就夠慢了的,還要每8個脈沖才捕捉一次,意味著相鄰兩次捕捉動作的間隔就更長。而這個例程代碼并沒有考慮到計數器溢出問題,或者說它是假設中間不會發生計數器溢出而設計的。

    直覺和經驗告訴我,很可能兩次捕捉間隔過長導致中途有計數器溢出事件發生,如果這樣自然測算不準了。于是提醒該他在做150Hz信號輸入捕捉測量時中途可能發生計數器溢出,建議其提高待測信號頻率驗證。后來他反饋當待測信號頻率提高到2.4K以上后就正確了【當然他這個數字是隨意選定的】,意思是說頻率高于一定數字后就OK了。

 

       看來的確是因為相鄰兩次捕捉動作的間隔過長導致中途有計數器溢出事件。我們可以大致計算下,假設定時器時鐘為16M,不發生溢出情況下能捕捉的最大間隔,即最慢頻率應該是16M/65536=24.4Hz, 這是最理想的情況,如果剛好錯過了第一個捕捉沿后就得等到下個周期的捕捉沿,要想不發生溢出,待測頻率最少也得48Hz以上。


現在他的待測信號頻率為150Hz時,加上做了捕捉事件8分頻,實測信號頻率相當于18.7Hz,遠低于不發生溢出要求的最慢頻率48Hz,不可避免的會發生溢出,導致測量錯誤。

       在代碼邏輯不變的情況下,我們可以考慮將定時器時鐘適當做分頻處理,當然不可無限制分頻,得兼顧測量精度需求。至于那個捕捉預分頻參數可以根據待測信號特征和測量需求調整。

       總之,上面STM8S定時器捕捉參考例程有其使用前提或局限性的。例程是通過查詢方式實現,每次開啟定時器后必須立馬進入捕捉,測量過程中還不可發生溢出,否則測量就出問題。如果有些應用場合中途溢出難免,那就得對代碼做些調整。

       其實,在STM32定時器應用時也可能碰到過類似問題。曾經有人反映用參考例程里的輸入捕捉代碼測量頻率時發現待測信號低到一定程度時就出現測量不正確的問題。

       下面是STM32F1系列固件庫輸入捕捉項目例程里的代碼:

STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\InputCapture

 

voidTIM3_IRQHandler(void)

{

  if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)

  {

    /* Clear TIM3 Capture compare interruptpending bit */

    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

    if(CaptureNumber == 0)

    {

      /* Get the Input Capture value */

      IC3ReadValue1 = TIM_GetCapture2(TIM3);

      CaptureNumber = 1;

    }

    else if(CaptureNumber == 1)

    {

      /* Get the Input Capture value */

      IC3ReadValue2 = TIM_GetCapture2(TIM3);

     

      /* Capture computation */

      if(IC3ReadValue2 > IC3ReadValue1)

      {

        Capture = (IC3ReadValue2 - IC3ReadValue1);   //N=0,未發生溢出;

      }

      else

      {

        Capture = ((0xFFFF - IC3ReadValue1) +IC3ReadValue2); //N=1發生1次溢出;

      }

      /* Frequency computation */

      TIM3Freq = (uint32_t) SystemCoreClock /Capture;

      CaptureNumber = 0;

    }

  }

}

    這個例程代碼使用了捕捉中斷,程序也是基于一個前提:待測信號時間長度不會長于65536個定時器計數脈沖,相比上面的STM8S的例程應該說有所改進,中途最多允許溢出一次。偶爾有些人對上面例程紅色代碼的第2條感到疑惑,那就是指中途發生過一次溢出的情形。比如第一次捕捉到的計數器的值是0Xeb3f, 中途發生過一次溢出后計數器重新開始計數,再第二次捕捉到的計算器的值完全比前一個捕捉值小。那有無可能中途只溢出一次,第2次捕捉到的數據比第一次還大呢?不可能,不信你可以把問題簡化下。在紙上書寫從0~9選擇任一個數字開始的10個連續的數看看。如果測量時中途發生1次以上的溢出事件時,該例程就有問題了。


    也就是說,STM32參考代碼里該例程也是使用前提的,盡管說它能滿足大部分的應用,作為代碼還是其局限性,當然代碼有局限性是絕對的,沒局限性的代碼猶如沒缺陷的人一樣不復存在。[就此打住,別扯太遠了。]

       STM32定時器的工作頻率高,很多情況下完全可以先做時鐘預分頻再做測量操作。如果個別應用情形下,計數器會不可避免地可能溢出多次怎么辦呢?其實只要搞清了原理,代碼怎么寫完全你自己掌握。在兩次捕捉之間,我們可以開啟溢出中斷,并對溢出中斷次數計數,假設中間發生了N次溢出中斷,始、止兩個捕捉數據value1value2。除第一個溢出不做滿量程計算外,其它N-1 個溢出中斷為滿量程計數。

 

整個計數脈沖個數=(65536-value1)+(N-1)*65536+value2

 

    上面等式中的N 可以是任意非負整數。不難看出當N=0=時,整個計數脈沖個數跟上面ST官方參考例程里兩處紅色代碼描述的是吻合一致的。

或許有細心的人看到,官方例程里用的是65535,我這里是65536。我認為這里應該是65536,不過具體到應用上,這1個脈沖誤差完全可以忽略不計了。

       上面提到的定時器都是假設其為16位的,所以計數器滿量程計數個數為65536。其實STM32家族中有不少系列都有32位的定時器,比如STM32F0STM32F3STM32F4STM32F7STM32L4系列中都帶32位定時器。

       搞清了原理,具體的代碼實現也就不難了,多了個溢出中斷次數計數,兩次捕捉間的計數脈沖個數統一用上面的等式即可。弄清了原理,就能自主地對參考性的東西做甄別和借鑒,然后自行調整相關軟硬件設計達到滿足應用需求之目的。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99热在这里只有精品 | 久草成人网 | 欧美在线一区二区三区 | 日本午夜视频 | 久久久精品黄色 | 成人欧美一区二区三区黑人孕妇 | 不卡视频一区 | 久操伊人 | www.日本在线观看 | 国产一区二区三区四区三区四 | 国产成人jvid在线播放 | 一区二区在线看 | 亚洲免费视频网址 | 精品久久久久久亚洲精品 | 日韩免费一区 | 欧美精品一二三区 | 久久精品一区二区三区四区 | av资源中文在线天堂 | 懂色av一区二区三区在线播放 | 天天亚洲| 神马久久春色视频 | 国产精品资源在线 | 黄网站涩免费蜜桃网站 | 久久一区二区三区电影 | 麻豆国产一区二区三区四区 | 日韩欧美视频免费在线观看 | 日韩一区精品 | 久久久激情 | 91精品久久久久 | 99久久成人 | 韩国电影久久 | 亚洲经典一区 | 中文字幕一区二区三区精彩视频 | 精品国产一区久久 | 欧美在线视频一区 | 夜夜骑首页| 精品乱码一区二区三四区 | 国产一区二区三区不卡av | 欧美一级久久久猛烈a大片 日韩av免费在线观看 | 毛片网在线观看 | 黄a在线观看 |