跳轉到內容

Hempl/PWM

來自華夏公益教科書
Mizar32 PWM LED 衰減的示例電路

PWM代表脈衝寬度調製,它是一種生成具有不同頻率的方波輸出訊號的方法,並且每個波形週期的一部分是低輸出或高輸出。

在設定PWM輸出時,您指定輸出的頻率(每秒高低變化的次數)及其佔空比(每個週期中多少百分比的時間處於高電平輸出)。

PWM輸出最常見的用法是使用固定頻率並改變佔空比,從而建立一種粗略的數字模擬轉換器來控制光的亮度或電機提供的功率。如果輸出訊號被放大以控制高功率裝置,這將導致更有效的系統,因為如果放大器一半時間全開,另一半時間全關,這比一直以一半功率執行浪費的能量更少。

另一種用途是使用固定佔空比並改變頻率來產生簡單的音效或管風琴音符,以生成具有方波波形的音調。在這種情況下,改變佔空比會改變產生的聲音的音調。

最後,PWM系統可以透過啟用PWM中斷來用於以固定的時間間隔生成中斷。這樣,每當PWM輸出的一個週期完成時,處理器就會停止它正在做的事情,執行一個稱為中斷例程的特殊程式碼片段,然後完成後,它將返回繼續中斷髮生之前正在做的事情。儘管硬體能夠做到這一點,但PWM中斷在Hempl中尚未實現。請參閱issue #5

硬體檢視

[編輯 | 編輯原始碼]

Mizar32有七個獨立的PWM輸出,儘管在電路圖上只有PWM0到PWM5被標記為PWM輸出。如果啟用PWM6,它將出現在標記為“GPIO50”的引腳上。

匯流排引腳
PWM AVR32引腳 匯流排引腳 PicoLisp 備註
PWM0 PB19 BUS4引腳7 'PB_19
PWM1 PB20 BUS4引腳8 'PB_20 也連線到JTAG引腳7“EVT0”
PWM2 PB21 BUS1引腳8 'PB_21
PWM3 PB22 BUS6引腳1 'PB_22
PWM4 PB27 BUS6引腳2 'PB_27
PWM5 PB28 BUS6引腳3 'PB_28
PWM6 PB18 BUS5引腳9 'PB_18 在Mizar32總線上,該引腳稱為“GPIO50”

軟體檢視

[編輯 | 編輯原始碼]

Hempl的PWM模組用於程式設計PWM引腳。

PWM6不可供使用者使用,因為它被內部用於提供系統計時器(PicoLisp中的*tmr-sys-timer*)。

輸出頻率和佔空比

[編輯 | 編輯原始碼]

使用兩個函式來獲得引腳上的某些PWM輸出。

(pwm-setup channel frequency duty_cycle)

設定輸出頻率和佔空比,其中channel(從0到6)是要使用的PWM通道,frequency(從1到1000000)確定輸出波形的頻率,單位為每秒週期數,duty_cycle(值從0到100)確定每個週期中波形輸出值處於高電平狀態的百分比。

(pwm-start channel)

設定振盪器執行以產生迴圈輸出波形。

如果在呼叫start函式之前呼叫了setup函式,正如我們剛剛描述的那樣,總線上的相應引腳將變為輸出引腳,在setup完成後輸出零伏,然後,當呼叫start時,輸出波形變為高電平,保持高電平一段時間,該時間佔週期的指定百分比,然後變為低電平,並保持低電平直到週期的剩餘時間,然後重複該過程,直到對同一通道呼叫stop為止。

或者,如果先呼叫start,則引腳將保持為輸入,直到呼叫setup,此時它將變為輸出並開始產生波形。

當呼叫stop時,PWM輸出始終完成當前週期;“停止”狀態意味著噹噹前週期完成後,它將不會開始一個新的週期,因此您可以透過這種方式獲得一個完整的輸出週期

在PicoLisp中

(pwm-setup 0 10 50)
(pwm-start 0)
(pwm-stop 0)

此程式程式碼將在整個週期輸出完成之前完成,請注意,當它“停止”時,引腳將繼續輸出0伏。

時鐘頻率

[編輯 | 編輯原始碼]

另一個函式

(pwm-setclock id freq)

允許您設定PWM時鐘頻率,該頻率高於輸出頻率,並決定輸出波形的時間粒度。實際上,PWM硬體每秒僅在1/freq的時間間隔內決定是否改變每個PWM引腳的輸出值,因此更高的時鐘頻率在時間和頻率方面提供更好的精度。

PWM時鐘頻率也決定了PWM輸出波形的最低和最高可能頻率:較低的時鐘頻率允許輸出頻率較低。

Mizar32上可能的時鐘頻率值從63Hz到16500000Hz。如果您要求超出此範圍的值,它將分別設定這兩個值的最低或最高值。在此範圍內,並非所有頻率都可用;它將設定最接近您要求的頻率的可用頻率,setclock()getclock()都返回一個整數,該整數是實際設定到PWM時鐘中的頻率。

雖然Hempl的setclockgetclock函式接受第一個引數來指定要設定時鐘的通道,但實際上硬體只有一個時鐘用於所有通道,因此為任何一個通道設定時鐘頻率將更改所有通道的時鐘頻率,以及更改任何正在執行的通道的當前輸出頻率。出於這個原因,setclock()通常只在設定各個通道之前呼叫一次。

PWM輸出頻率的範圍和精度

[編輯 | 編輯原始碼]

在Hempl中,setup函式的引數只關注數字的整數部分,忽略任何小數部分,因此您可以要求的最低頻率為每秒一個週期,最高精度為一赫茲。

此外,硬體只能生成某些頻率(這些頻率是時鐘頻率的精確除數),setup返回一個整數,該整數最接近實際設定的輸出頻率,這可能與您要求的頻率不同。

例如,使用預設的 1 兆赫時鐘頻率,您可以設定從 1 到 1037 的任何整數頻率,但 1038 將為您提供 1039,然後越來越多的值變得越來越不精確,直到我們來到最高可用的頻率 250000Hz、333333Hz、500000Hz 和 1000000Hz,這些頻率分別是時鐘頻率除以 4、3、2 和 1。

相反,在最高時鐘頻率 16500000Hz 時,可以獲得從 16Hz 到 4105Hz 的所有整數頻率,高於此頻率,可以獲得更廣泛的值範圍,這更適合電子琴等應用,在這些應用中,高音符頻率的準確性比生成極低音符更重要。

使用 PWM 引腳作為 PIO 引腳

[編輯 | 編輯原始碼]

如果某個特定的 PWM 輸出沒有用於 PWM 輸出,您可以簡單地透過在該引腳上呼叫 pio 模組中的函式來將其用作通用 PIO 引腳。

如果您希望一個用於 PWM 輸出的引腳完全停止輸出電壓,也可以使用此方法:您將呼叫

(pio-pin-setdir *pio-input* 'PB_xx)

其中 xx 是上面表格中該 PWM 通道的引腳編號。

示例程式碼

[編輯 | 編輯原始碼]
# Make the LED slowly fade up and down forever

# Connect a LED in series with a
# 330 ohm resistor between PWM0 pin
# (BUS4 pin 7) and GND (BUS4 pin 1)

(setq
   pwmid 0 # Which channel to use?
   speed 3000 # PWM frequency in Hz
   fadetime 1 # How many secs to fade up?
   nsteps 100 ) # How many steps in the fade?

(setq delay (/ (* (pwm-getclock tmrid) fadetime)
               nsteps ) )

(pwm-start pwmid)

(loop
   # Fade the LED up
   (for duty nsteps
      (pwm-setup pwmid speed duty)
      (tmr-delay *tmr-sys-timer* delay) )
   
   # Fade the LED down
   (for (i nsteps (ge0 i) (dec i))
      (pwm-setup pwmid speed i)
      (tmr-delay *tmr-sys-timer* delay) ) )

進一步閱讀

[編輯 | 編輯原始碼]
華夏公益教科書