在前一小節(jié)中介紹了點亮第一個LED燈,這里我們準備進階嘗試下,輸出第一段PWM波形。(PWM也就是脈寬調(diào)制,一種可調(diào)占空比的技術(shù),得到的效果就是:如果用示波器測量引腳會發(fā)現(xiàn)有方波輸出,而且高電平、低電平的時間是可調(diào)的。)
為平南等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務,及平南網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務為網(wǎng)站設(shè)計制作、成都網(wǎng)站制作、平南網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
這里爪爪熊準備寫成一個golang的庫,并開源到github上,后續(xù)更新將直接更新到github中,如果你有興趣可以和我聯(lián)系。 github.com/dpawsbear/bear_rpi_go
我在很多的教程中都看到說樹莓派的PWM(硬件)只有一個GPIO能夠輸出,就是 GPIO1 。這可是不小的打擊,因為我想使用至少四個 PWM ,還是不死心,想通過硬件手冊上找尋蛛絲馬跡,看看究竟怎么回事。
手冊上找尋東西稍等下講述,這里先提供一種方法測試 樹莓派3B 的 PWM 方法:用指令控制硬件PWM。
這里通過指令的方式掌握了基本的pwm設(shè)置技巧,決定去翻一下手冊看看到底PWM怎么回事,這里因為沒有 BCM2837 的手冊,根據(jù)之前文章引用官網(wǎng)所說, BCM2835 和 BCM2837 應該是一樣的。這里我們直接翻閱 BCM2835 的手冊,直接找到 PWM 章節(jié)。找到了如下圖:
圖中可以看到在博通的命名規(guī)則中 GPIO 12、13、18、19、40、41、45、52、53 均可以作為PWM輸出。但是只有兩路PWM0 PWM1。根據(jù)我之前所學知識,不出意外應該是PWM0 和 PWM1可以輸出不一樣的占空比,但是頻率應該是一樣的。因為沒有示波器,暫時不好測試。先找到下面對應圖:
根據(jù)以上兩個圖對比可以發(fā)現(xiàn)如下規(guī)律:
對照上面的表可以看出從 BCM2837 中印出來的能夠使用在PWM上的就這幾個了。
為了驗證個人猜想是否正確,這里先直接使用指令的模式,模擬配置下是否能夠正常輸出。
通過上面一系列指令模擬發(fā)現(xiàn),(GPIO1、GPIO26)、(GPIO23、GPIO24)是綁定在一起的,調(diào)節(jié)任意一個,另外一個也會發(fā)生變化。也即是PWM0、PWM1雖然輸出了兩路,可以理解成兩路其實都是連在一個輸出口上。這里由于沒有示波器或者邏輯分析儀這類設(shè)備(僅有一個LED燈),所以測試很簡陋,下一步是使用示波器這類東西對頻率以及信號穩(wěn)定性進行下測試。
小節(jié):樹莓派具有四路硬件輸出PWM能力,但是四路中只能輸出兩個獨立(占空比獨立)的PWM,同時四路輸出的頻率均是恒定的。
上面大概了解清楚了樹莓派3B的PWM結(jié)構(gòu),接下來就是探究如何使用Go語言進行設(shè)置。
因為拿到了手冊,這里我想直接操作寄存器的方式進行設(shè)置,也是順便學習下Go語言處理寄存器的過程。首先需要拿到pwm 系列寄存器的基地址,但是翻了一圈手冊,發(fā)現(xiàn)只有偏移,沒有找到基地址。
經(jīng)過了一段時間的努力后,決定寫一個 樹莓派3B golang包開源放在github上,只需要寫相關(guān)程序進行調(diào)用就可以了,以下是相關(guān)demo(pwm)(在GPIO.12 上輸出PWM波,放上LED燈會有呼吸燈的效果,具體多少頻率還沒有進行測試)
以下是demo(pwm) 源碼
因為Java是以沙箱機制運行的,進程間隔離,要想用Java寫外掛也不是完全不可以,只是先得用C/C++編寫注入程序(通常是動態(tài)鏈接庫),然后用JNI方式編寫其Java擴展。
至于Go語言,不太了解。但是外掛主要是指ABI層次的,和語言無關(guān),只要一種語言的調(diào)用約定符合你要注入的程序的調(diào)用約定(以Windows為例就是WindowsAPI)都可以的(Java就是和C語言的調(diào)用約定不同所以不能直接寫外掛)。
關(guān)于注入的技巧,可以中搜這個文章
Three
Ways
to
Inject
Your
Code
into
Another
Process
或中文《注入代碼的
3
種方法》
基本設(shè)計思路:
類型轉(zhuǎn)換、類型斷言、動態(tài)派發(fā)。iface,eface。
反射對象具有的方法:
編譯優(yōu)化:
內(nèi)部實現(xiàn):
實現(xiàn) Context 接口有以下幾個類型(空實現(xiàn)就忽略了):
互斥鎖的控制邏輯:
設(shè)計思路:
(以上為寫被讀阻塞,下面是讀被寫阻塞)
總結(jié),讀寫鎖的設(shè)計還是非常巧妙的:
設(shè)計思路:
WaitGroup 有三個暴露的函數(shù):
部件:
設(shè)計思路:
結(jié)構(gòu):
Once 只暴露了一個方法:
實現(xiàn):
三個關(guān)鍵點:
細節(jié):
讓多協(xié)程任務的開始執(zhí)行時間可控(按順序或歸一)。(Context 是控制結(jié)束時間)
設(shè)計思路: 通過一個鎖和內(nèi)置的 notifyList 隊列實現(xiàn),Wait() 會生成票據(jù),并將等待協(xié)程信息加入鏈表中,等待控制協(xié)程中發(fā)送信號通知一個(Signal())或所有(Boardcast())等待者(內(nèi)部實現(xiàn)是通過票據(jù)通知的)來控制協(xié)程解除阻塞。
暴露四個函數(shù):
實現(xiàn)細節(jié):
部件:
包: golang.org/x/sync/errgroup
作用:開啟 func() error 函數(shù)簽名的協(xié)程,在同 Group 下協(xié)程并發(fā)執(zhí)行過程并收集首次 err 錯誤。通過 Context 的傳入,還可以控制在首次 err 出現(xiàn)時就終止組內(nèi)各協(xié)程。
設(shè)計思路:
結(jié)構(gòu):
暴露的方法:
實現(xiàn)細節(jié):
注意問題:
包: "golang.org/x/sync/semaphore"
作用:排隊借資源(如錢,有借有還)的一種場景。此包相當于對底層信號量的一種暴露。
設(shè)計思路:有一定數(shù)量的資源 Weight,每一個 waiter 攜帶一個 channel 和要借的數(shù)量 n。通過隊列排隊執(zhí)行借貸。
結(jié)構(gòu):
暴露方法:
細節(jié):
部件:
細節(jié):
包: "golang.org/x/sync/singleflight"
作用:防擊穿。瞬時的相同請求只調(diào)用一次,response 被所有相同請求共享。
設(shè)計思路:按請求的 key 分組(一個 *call 是一個組,用 map 映射存儲組),每個組只進行一次訪問,組內(nèi)每個協(xié)程會獲得對應結(jié)果的一個拷貝。
結(jié)構(gòu):
邏輯:
細節(jié):
部件:
如有錯誤,請批評指正。
最近在做一個內(nèi)網(wǎng)穿透工具,是用C# Dotnet Core寫的。 總擔心性能不行,想?yún)⒖枷聞e人寫的。 結(jié)果搜到很多GO語言的例子。 看了下Go語言的介紹,覺得確實是比較簡單的語言。并且在并發(fā)上比較方便。于是,就開始學習Go語言,并用Go把內(nèi)網(wǎng)穿透工具重新寫了一下。
然后,又想用Go語言重寫之前的DotnetCore的WebAPI,現(xiàn)在還在編寫中,只是對比下兩個語言差異。
然后看下 C#
實際上目前我也沒有能力判斷GO和C#哪個更好
網(wǎng)站題目:包含GO語言寫刮削器的詞條
標題鏈接:http://www.chinadenli.net/article18/hpgjgp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計、網(wǎng)站制作、定制網(wǎng)站、定制開發(fā)、用戶體驗、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)