如何使用定時器產生兩路頻率可調的PWM波

2021-09-11 22:35:31 字數 3209 閱讀 7188

輸出頻率可調的方波(占空比不可調,預設為50%)

使用定時器來產生pwm波大家應該都很熟悉,但是如何使用定時器產生頻率可調的pwm波呢?這就需要使用定時器的輸出比較翻轉模式tim_ocmode_toggle

先大概介紹一些這個模式是如何工作的:

輸出比較翻轉,顧名思義,就是程式執行的過程中,會一直拿計數器的當前計數值和比較暫存器中的值進行比較,如果當前計數值和比較暫存器中的值相等了,那麼就會產生輸入/捕獲中斷,然後定時器會自動地翻轉當前的電平輸出狀態,然後再往比較暫存器中加上乙個定值(也就是程式中的ccr1_valccr2_val),讓計數器中的值繼續去追趕更新後的比較暫存器中的值,以使得定時器還是相隔相同的時間去產生下一次輸入捕獲中斷。

先來看下定時器以及pwm波輸出配置程式:

void pwmout_init_adjust_fre(void)//輸出兩路頻率可調的pwm波

上面這個配置程式完成的工作就是配置定時器得到基本引數,包括計數週期、計數計數頻率以及pwm工作的模式等等。

下面再來看一下中斷服務函式我們都幹了啥:

void tim3_irqhandler(void)

if(tim_getitstatus(tim3,tim_it_cc2) != reset)

}

首先我們要明白這個中斷是如何產生的,if(tim_getitstatus(tim3,tim_it_cc1) != reset)代表的就是捕獲/比較中斷,也就是意味著計數器中的值和當前比較暫存器中的值相等的時候,就會產生這樣乙個捕獲/比較中斷。產生中斷之後,我們首先要清零中斷標誌位tim_clearitpendingbit(tim3,tim_it_cc1);

然後用乙個全域性變數capture去獲取當前計數器當中的值,然後下一步就是重要的一步了,下一步就是更新比較暫存器中的值,那麼到底更新成多少,才能保證再隔相同的時間產生下一次捕獲/比較中斷呢?因為計數值是一直向上計數的,所以為了使下一次計數值還能和比較暫存器中的值相等,那肯定比較暫存器的值也要增加,為了使每次產生捕獲/比較中斷都是相同的時間間隔,所以我們就需要把當前計數器中的值加上ccr1_val重新賦值給比較暫存器,也就是每次都得讓更新後的比較暫存器中的值比當前計數器中的值大上乙個變數ccr1_val的值,也就是這一句**tim_setcompare1(tim3,capture + ccr1_val);

如果還不理解,我再舉乙個簡單的小栗子:

假如現在計數器的值為0,比較暫存器中的值為600(即ccr1_val初始化為600),此時對應的pwm輸出引腳輸出低電平,然後計數器開始向上計數,0,1,2,3,…,597,598,599,600,當計數器一直加到600的時候,也就是當計數器中的值與比較暫存器中的值相等的時候,就會產生乙個捕獲/比較中斷,在中斷函式裡面,我們要做的就是先獲取當前計數器中的值,也就是capture = tim_getcapture1(tim3);,即當前的capture =600。然後,在把新的值capture + ccr1_val,也就是600+600重新賦值給比較暫存器中,也就是tim_setcompare1(tim3,capture + ccr1_val),賦值完成之後,此時計數器中的值還是600,而比較暫存器中的值更新為600+600=1200。此時定時器會自動翻轉對應的pwm輸出引腳的電平狀態,即翻轉為高電平。然後退出中斷服務函式,計數器計數開始往上計數,600,601,601,…,1198,1199,1200,當計數器加到1200的時候,計數器的值又和比較暫存器中的值相等了,即又會產生一次捕獲/比較中斷,又進入到了中斷服務函式,還是重複剛才的動作,首先清零中斷標誌位,然後獲取當前計數器中的值capture = tim_getcapture1(tim3);,即當前的capture =1200。然後再把當前新的值capture + ccr1_val,也就是1200+600重新賦值給比較暫存器中,也就是tim_setcompare1(tim3,capture + ccr1_val),賦值完成之後,此時計數器中的值還是1200,而比較暫存器中的值更新為1200+600=1800。此時定時器仍然會自動翻轉對應的pwm輸出引腳的電平狀態,即翻轉為低電平,然後退出中斷服務函式,計數器計數向上計數,然後等待著下一次計數器中的值與比較暫存器中的值1800相等時,又會產生一次捕獲/比較中斷,在中斷裡面還是重複剛才的幾個動作,即清零中斷標誌位、獲取當前計數值器中的值以及更新比較暫存器中的值,就這樣,一直迴圈下去,就可以產生占空比為50%的方波。

注意在上面的過程中,變化的是計數器中的值和比較暫存器中的值,不變的是變數ccr1_val,在上面的例子中ccr1_val一直等於600,也就是這個ccr1_val控制著pwm波的頻率。假如說計數頻率為1mhz,也就是1us計乙個數,那麼pwm波輸出的週期就是ccr1_val*2us,因為占空比為50%,所以乙個pwm波的週期內高低電平的時間均為ccr1_val。假如說ccr1_val=1000,那麼pwm波週期就是1000*2us=2ms,也就是500hz。然後我們通過調節這個ccr1_val的值,就可以實時的改變pwm波輸出的頻率了。

再來補充一下,如果比較暫存器的值加的過程超過了65535怎麼辦:

結果就是,超過了也沒事,反正計數器和比較暫存器中的值都是最大到65535。假如說現在比較暫存器和計數器相等了,並且都等於65530,然後比較暫存器又加上了乙個數100,那麼他現在的值就是94(超過65535之後,又從0開始),那麼計數器也是從65530開始乙個乙個往上加的,它的計數過程也是65530,65531,…65535,0,1…94,也就是說超過了65535之後,他倆由於是同樣的計數規則,所以說並不影響每次產生中斷的時間間隔。

下篇部落格介紹頻率可調、占空比可調的pwm波輸出

參考部落格:

1、輸出頻率可調、占空比可調的pwm波

2、藍橋杯嵌入式比賽備賽手冊

stm32定時器輸出4路頻率可調的原理分析

1標題說不清楚,簡單點說就是乙個定時器輸出4路可調節頻率的pwm。2這個功能能幹嘛?一般是用於控制多個步進電機。這樣做乙個定時器就可以控制4個電機了。先上 吧 u16 capture 0 vu16 ccr1 val 32768 vu16 ccr2 val 16384 vu16 ccr3 val 81...

STM32一定時器產生不同頻率的PWM

f ef bc 81 details 平時記性實在太差,除錯完的程式,過兩天又忘了,往往需要一陣子才能想起來,有時以前的資料找不到了,更是惱火,不得不重複到網上搜尋。剛剛除錯成功了乙個型別的程式,立刻記下來,呵呵,不要又忘記了。stm32產生pwm是非常的方便的,要需要簡單的設定定時器,即刻產生!當...

7 使用定時器去掉按鍵輸入中產生抖動

1.電路圖 2.linux核心中使用定時器的步驟static struct timer list timer 定義全域性的定時器 init timer timer 初始化定時器 buttons timer.function function 設定超時呼叫函式 buttons timer.expire...