2011年5月31日 星期二
惱人的pwm duty cycle setting for PIC
PIC在使用hardware的pwm module(CCP1)時, 需要設定PWM的頻率如下
這個部份大家應該都沒有問題, 通常比較有問題的是pwm的duty cycle, 先看下面的pwm duty的公式
如果按照我們既有的觀念去算, 假設我的Tosc=0.05uS(20M OSC), TMR2 prescale value=1, PR2=49則PWM frequency=100KHz, 如果我要得到50%的duty cycle, 則計算如下
(CCPRxL:CCPxCON<5:4>)=PWM Duty Cycle/(Tosc*TMR2 Prescale Value)
=(50/100)/(0.05u*1)=10000000
疑? 真奇怪, 我完全按照公式去算啊, 為啥不對, CCPRxL:CCPxCON<5:4>總共是10個bit, 所以可設定範圍為0~1023, 那為什麼會得到10000000
花了二個小時去找為什麼, 最後終於發現為什麼了, 老外的思考和咱們就是有差, 原因是出在pic spec上寫的pwm duty cycle的解讀不同, 看下面
spec上寫的pwm duty cycle => 指的是PWM pulse width
我的認知 pwm duty cycle => 指的是百分比的工作週期
所以按照我所認知的duty cycle應該要代入下面的公式
我們按照上面的條件再算一次
(CCPRxL:CCPxCON<5:4>)=PWM Duty Cycle Ratio* 4(PR2+1)
=(50/100)*4(49+1)=100
請注意, 另一個陷阱來了, 這個是10bit的100喔, 而不是8bit的100, 差別如下
10 bit的100以2進制來看為0110010000 => 換成十進制為400
8 bit的100以2進制來看為01100100 => 換成十進制為100
真的是差很大, 所以正確的做法有二種
1. 宣告duty為int16的變數 , 如 int16 duty;
2. 直接給duty的數值, 如 set_pwm1_duty(100L); => 100L會通知compiler以long來做運算
我是建議用第一種方法, 因為很多人都應該會忘了在數值後面加個"L"
最後, 我們再驗證一次equation 15-2
(CCPRxL:CCPxCON<5:4>)=PWM Pulse width/(Tosc*TMR2 Prescale Value)
=((1/100000)*(50/100))/(0.05u*1)
=5u/0.05u
=100
果然這樣就對了, 希望大家不要和我一樣多花了2~3個小時在這種地方, 很不值得, 所以寫出來和大家分享!!
訂閱:
張貼留言 (Atom)
圖片失效了 可以補圖我會很感激@@
回覆刪除我找找, 但不見得找得到
刪除