這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在前一小節中介紹了點亮第一個LED燈,這裡我們準備進階嘗試下,輸出第一段PWM波形。(PWM也就是脈寬調製,一種可調占空比的技術,得到的效果就是:如果用示波器測量引腳會發現有方波輸出,而且高電平、低電平的時間是可調的。)
這裡爪爪熊準備寫成一個golang的庫,並開源到github上,後續更新將直接更新到github中,如果你有興趣可以簡書和我聯絡。 github.com/dpawsbear/bear_rpi_go
一、樹莓派的PWM
我在很多的教程中都看到說樹莓派的PWM(硬體)只有一個GPIO能夠輸出,就是 GPIO1。這可是不小的打擊,因為我想使用至少四個 PWM ,還是不死心,想通過硬體手冊上找尋蛛絲馬跡,看看究竟怎麼回事。
手冊上找尋東西稍等下講述,這裡先提供一種方法測試 樹莓派3B 的 PWM 方法:用指令控制硬體PWM。
#pwm 輸出頻率為4.8Mhz/1024 = 4.6875khzgpio mode 1 pwm # 設定 gpio1 引腳為pwm模式gpio pwm-ms # 設定 pwm 的模式為 pwm-ms Mark-spacegpio pwmr 1024 # 設定 pwm 滿計數為1024gpio pwmc 4 # 設定 pwm 的頻率 4:4.8MHZgpio pwm 1 512 # 設定 pwm 的占空比 為 512/1024 (50%)占空比
這裡通過指令的方式掌握了基本的pwm設定技巧,決定去翻一下手冊看看到底PWM怎麼回事,這裡因為沒有 BCM2837 的手冊,根據之前文章引用官網所說, BCM2835 和 BCM2837 應該是一樣的。這裡我們直接翻閱 BCM2835 的手冊,直接找到 PWM 章節。找到了如:
image.png
圖中可以看到在博通的命名規則中 GPIO 12、13、18、19、40、41、45、52、53 均可以作為PWM輸出。但是只有兩路PWM0 PWM1。根據我之前所學知識,不出意外應該是PWM0 和 PWM1可以輸出不一樣的占空比,但是頻率應該是一樣的。因為沒有示波器,暫時不好測試。先找到下面對應圖:
image.png
根據以上兩個圖對比可以發現如下規律:
| PWMn |
BCM引腳 |
GPIO引腳(NAME) |
板子引腳 |
複用模式 |
| PWM0 |
GPIO 12 |
GPIO26 |
32 |
ALT0 |
| PWM0 |
GPIO 18 |
GPIO 1 |
12 |
ALT5 |
| PWM1 |
GPIO 13 |
GPIO23 |
33 |
ALT0 |
| PWM1 |
GPIO 19 |
GPIO24 |
35 |
ALT5 |
對照上面的表可以看出從 BCM2837 中印出來的能夠使用在PWM上的就這幾個了。
為了驗證個人猜想是否正確,這裡先直接使用指令的模式,類比配置下是否能夠正常輸出。
# 指令方式類比配置 gpio為pwmgpio mode 1 pwmgpio mode 26 pwmgpio mode 23 pwmgpio mode 24 pwmgpio pwm-msgpio pwmr 1024gpio pwm 1 100gpio pwm 26 512gpio pwm 23 10gpio pwm 24 256
通過上面一系列指令類比發現,(GPIO1、GPIO26)、(GPIO23、GPIO24)是綁定在一起的,調節任意一個,另外一個也會發生變化。也即是PWM0、PWM1雖然輸出了兩路,可以理解成兩路其實都是連在一個輸出口上。這裡由於沒有示波器或者邏輯分析儀這類裝置(僅有一個LED燈),所以測試很簡陋,下一步是使用示波器這類東西對頻率以及訊號穩定性進行下測試。
小節:樹莓派具有四路硬體輸出PWM能力,但是四路中只能輸出兩個獨立(占空比獨立)的PWM,同時四路輸出的頻率均是恒定的。
二、使用go語言操作PWM
上面大概瞭解清楚了樹莓派3B的PWM結構,接下來就是探究如何使用Go語言進行設定。
因為拿到了手冊,這裡我想直接操作寄存器的方式進行設定,也是順便學習下Go語言處理寄存器的過程。首先需要拿到pwm 系列寄存器的基地址,但是翻了一圈手冊,發現只有位移,沒有找到基地址。
經過了一段時間的努力後,決定寫一個 樹莓派3B golang包開源放在github上,只需要寫相關程式進行調用就可以了,以下是相關demo(pwm)(在GPIO.12 上輸出PWM波,放上LED燈會有呼吸燈的效果,具體多少頻率還沒有進行測試)
2.1 使用方法
go get github.com/dpawsbear/bear_rpi_gocd $gopath/src/github.com/dpawsbear/bear_rpi_go/examplego build -ldflags "-w -s" pwm.gosudo ./pwm
以下是demo(pwm) 源碼
package mainimport ( "fmt" rpi "github.com/dpawsbear/bear_rpi_go" "time")func main(){ fmt.Println("starting...") if 0 != rpi.Bcm2837_init() { rpi.Bcm2837_close() panic(55) return } //test for pwm (GPIO.12 and GND) rpi.Bcm2837_gpio_fsel(rpi.RPI_3B_GPIO_J8_12,uint8(rpi.BCM2837_GPIO_FSEL_ALT5)) rpi.Bcm2837_pwm_set_clock(rpi.BCM2837_PWM_CLOCK_DIVIDER_16) rpi.Bcm2837_pwm_set_mode(0, 1, 1 ) rpi.Bcm2837_pwm_set_range(0,1024 ) rpi.Bcm2837_pwm_set_data(0,10 ) var data uint32 = 1 for{ for { time.Sleep(time.Millisecond*2) data ++ if data > 768{ break } rpi.Bcm2837_pwm_set_data(0,data ) } for { time.Sleep(time.Millisecond*2) data -- if data < 2 { data = 1 break } rpi.Bcm2837_pwm_set_data(0,data ) } }}