有人使用STM32晶片開發産品,其中有個功能就是統計某外部信号脈沖個數。他采用外部中斷方式,來一個信号觸發一次中斷,在中斷程式裡實作計數累加。但由于被統計的信号頻率較高,而中斷本身也是需要時間的,往往導緻有些脈沖沒被統計而發生丢數的問題。況且,CPU這樣頻繁地去響應中斷還會衍生出其它系統性問題。
他咨詢是否可以将該信号作為定時器的時鐘源,每來一個脈沖信号計數器就自動加1。這樣的話,使用者适時去讀取計數器的值即可。若有,如何實作?
對于這種情況,我們可以将被統計信号連接配接到定時器的ETR腳,并作為定時器的計數時鐘。開啟定時器更新中斷對溢出次數進行統計,擇時讀取計數器的值和溢出次數即可。這樣既避免了CPU頻繁進中斷而無法應對别的事情的困境,也避免了因CPU優先忙于别的事情而來不及響應外部中斷導緻計數出錯的麻煩。
對于STM32來講,從ETR腳引入時鐘信号,可以有兩種模式。
第一種模式,即外部時鐘1模式,此時來自ETR腳的信号經過濾波、邊沿檢測和極性選擇後,以觸發信号的角色連接配接到從模式控制器,并作為定時器的時鐘源,即上圖中的1路。
第二種模式,即外部時鐘2模式,來自ETR腳的時鐘信号經過極性選擇、分頻、濾波後不經過從模式控制器,而是像内部時鐘源一樣直接為計數器提供計數時鐘,即上圖中的2路。
現在分别以上面提到的兩種模式示範定時器對來自ETR腳的時鐘信号進行計數的過程。這裡以STM32F411 Nucleo開發闆來進行實驗。
用TIM1_CH1模拟産生某頻率的PWM脈沖信号,将其通過跳線連接配接到ETR腳。為便于測量和示範,讓TIM1工作在單脈沖PWM模式,結合RCR寄存器輸出指定個數的脈沖。使用TIM3對來自ETR腳的時鐘信号進行計數,同時開啟TIM3更新中斷對溢出次數進行統計。
讓TIM1-CH1啟動後輸出248個脈沖後停下來,而TIM3每統計200個脈沖就産生溢出,即令TIM3_ARR值等于199。
現在使用STM32CUBEMX進行基本的配置。
先對用來模拟産生外來脈沖信号的TIM1進行配置。做些基本的時基配置即可。
然後對TIM3進行配置,時鐘來自ETR腳,工作在外部時鐘模式2。
将時鐘、NVIC等配置完畢後即可生成初始化代碼。
定義變量CNT_Update記錄TIM3的溢出次數。基于STM32Cube 庫稍加組織代碼即可檢視結果。
編譯運作檢視結果:
TIM3發生溢出1次,結合上面配置可知其對應的脈沖個數為200,此時計數器裡的值為0x30,即48,總共248個脈沖,跟TIM1_CH1輸出的248個脈沖數相同。
上面的實驗是基于TIM3工作在ETR外部時鐘模式2,我們不妨再看看基于外部時鐘模式1的情況。現在隻需對TIM3的時鐘配置稍作調整,其它參數不動。
生成初始化代碼後,基于前面組織的使用者代碼不做任何調整即可編譯運作驗證。
上面驗證結果與外部時鐘模式2完全相同,跟TIM1_CH1輸出的脈沖數完全吻合。
從上面示例來看,當時鐘信号來自ETR腳時,不論使用外部時鐘模式1還是外部時鐘模式2,都可以實作完全相同的結果。那麼基于同一個時鐘源,為什麼弄出2個時鐘模式呢?
首先,定時器本身支援多鐘時鐘模式,其中包括外部時鐘模式1與外部時鐘模式2。隻不過來自ETR腳的時鐘信号既可以工作外部時鐘模式1,也可以工作在外部時鐘模式2。
外部時鐘模式1的主要特點是時鐘信号還同時兼具觸發信号的角色,此時定時器也一定工作在從模式,這個從模式就是外設時鐘模式1從模式。STM32參考手冊關于這個模式,在講解定時器主從連接配接的相關執行個體時進行過介紹,但沒有将其跟複位從模式、觸發從模式等從模式一起單列出來進行介紹。我們在用STM32CubeMX進行配置時也可以發現有個從模式選項就是外部時鐘1從模式。
前面也提到了,外部時鐘模式1下的時鐘除了做時鐘外,還做觸發信号。基于這個觸發信号可以産生觸發事件,進而觸發中斷或産生DMA請求。而外部時鐘模式2就是特指來自ETR腳的時鐘,隻是個純粹的時鐘,不具備觸發功能。但是,選擇外部時鐘模式2的定時器,既可以工作在主模式,也可以工作在諸如複位/觸發/門控等從模式。
另外,作為外部時鐘模式1的時鐘,它可以有多個來源,除了ETR腳外,還可以是TI1、TI2輸入腳或者其它定時器的觸發輸出,而工作在外部時鐘模式2的時鐘隻能來自ETR腳。顯然,基于開篇的客戶需求,它的被測信号還可以接到别的特定管腳上來處理。
最後做點提醒。基于上面應用,弄清實作原理後,自行組織使用者代碼應該說非常簡單了。不過,即使這樣,可能還是會有不少人在有個地方出問題,就是沒有下圖中那句對TIM3的更新事件标志進行清零的代碼。很多場景,這行代碼可有可無。當遇到目前這種應用時,就不能可有可無了。
基于上面的程式邏輯,如果沒有這句代碼會發生統計所得的溢出次數與實際溢出次數多1的狀況。以上面應用為例,我什麼都不改動,隻将那行代碼注釋掉,運作結果會變成下面的樣子。計數器裡的值雖然還是48,但溢出次數變成2了!
像這種需要統計精确資料的情形,發生這種問題往往就難以接受。為什麼要加這句代碼呢?如果不加這句代碼怎麼會導緻統計到的溢出次數平白無故多1次呢?
關于這點可以自行思考下,在此不延申解釋了。也可以參考下面文章《STM32定時器中的更新操作與更新事件》的結尾部分,那裡有就該問題做些分析。
==========================
往期話題閱讀連結【點選閱讀】:
1、四個ADC子產品同時轉換之應用示例
2、一個低功耗應用的案例分析
3、STM32定時器中的更新操作與更新事件
4、一個跟狀态位處理有關的應用案例
5、調試過程中跟工具相關的幾個問題