0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

樹莓派Pico如何使用PIO程序呢?

jf_zGNBEhbi ? 來源:趣無盡 ? 2023-11-14 15:06 ? 次閱讀

在這篇教程中,我們看到的代碼看起來與其他的部分的代碼非常不同。那是因為我們大多數(shù)時候不得不在 MCU 的底層處理事情。大多數(shù)時候,MicroPython 可以隱藏很多在微控制器上工作的復(fù)雜性。
當(dāng)我們 print(“hello”) 的時候,我們不必擔(dān)心微控制器存儲字母的方式,或它們被發(fā)送到串行終端的格式,或串行終端所接受的時鐘周期的數(shù)量。這些都是在后臺處理的。然而,當(dāng)我們進入可編程輸入和輸出時(PIO),我們需要在更低的層次上處理這些邏輯。

我們將簡要介紹 PIO,并介紹一些高級主題,以便你了解正在發(fā)生的事情,并希望了解 Pico 上的 PIO 相對于其他微控制器是如何突顯優(yōu)勢的。但是,理解創(chuàng)建 PIO 程序所需的所有低級數(shù)據(jù)操作需要花時間來完全理解,所以如果它看起來有點不透明也不用擔(dān)心。如果你對處理這種低級編程感興趣,那么我們將幫助你入門。如果你更感興趣的是在更高的層次上工作,而寧愿把低層次的爭論留給其他人,我們將向你展示如何使用 PIO 程序。

數(shù)據(jù)輸入和數(shù)據(jù)輸出

樹莓派 Pico 不僅支持 SPI 和 I2C 控制器發(fā)送數(shù)據(jù)。它還有自己的特殊協(xié)議:可編程 IO。讓我們看一個例子:

from rp2 import PIO, StateMachine, asm_pio
from machine import Pin
import time


@asm_pio(set_init=PIO.OUT_LOW)
def led_quarter_brightness():
  set(pins, 0)[2]
  set(pins, 1)


@asm_pio(set_init=PIO.OUT_LOW)
def led_half_brightness():
  set(pins, 0)
  set(pins, 1)


@asm_pio(set_init=PIO.OUT_HIGH)
def led_full_brightness():
  set(pins, 1)


sm1 = StateMachine(1, led_quarter_brightness, freq=10000, set_base=Pin(25))
sm2 = StateMachine(2, led_half_brightness, freq=10000, set_base=Pin(25))
sm3 = StateMachine(3, led_full_brightness, freq=10000, set_base=Pin(25))


while(True):
  sm1.active(1)
  time.sleep(1)
  sm1.active(0)
  sm2.active(1)
  time.sleep(1)
  sm2.active(0)
  sm3.active(1)
  time.sleep(1)
  sm3.active(0)

這些方法實際上是運行在 PIO 狀態(tài)機上的小程序,且在不斷循環(huán)。例如,led_half_brightness() 會不斷地打開和關(guān)閉 LED,這樣 LED 就會有一半的時間是關(guān)閉的,一半的時間是打開的。led_full_brightness() 將類似地循環(huán),但由于惟一的指令是打開 LED,這實際上并沒有改變?nèi)魏螙|西。

這里稍微有點不尋常的是 led_quarter_brightness()。每個 PIO 指令只需要運行一個時鐘周期(可以通過設(shè)置頻率來更改時鐘周期的長度,稍后我們將看到)。但是,我們可以在一條指令之后用方括號添加一個 1 到 31 之間的數(shù)字,來告訴 PIO 狀態(tài)機在運行下一條指令之前暫停這個時鐘周期。

然后,在 led_quarter_brightness() 中,兩個 set 指令每個使用一個時鐘周期,延遲使用兩個時鐘周期,因此總循環(huán)使用四個時鐘周期。在第一行中,set 指令需要一個周期,延遲需要兩個周期,所以 GPIO 管腳在這四個周期中的三個是關(guān)閉的。這使得 LED 的亮度達到了持續(xù)亮燈的四分之一。

一旦設(shè)定了 PIO 程序,Pico 就需要將其加載到狀態(tài)機中。因為我們有三個程序,所以需要將它們加載到三個狀態(tài)機中(有 8 個狀態(tài)機可以使用,編號為 0-7)。這可以用下面一行來實現(xiàn):

sm1 = StateMachine(1, led_quarter_brightness, freq=10000, set_base=Pin(25))

參數(shù)如下:
– 狀態(tài)機器編號
– PIO 程序加載
– 頻率(必須在 2000 到 125000000 之間)
– 狀態(tài)機器操縱的 GPIO 引腳

還有一些額外的參數(shù),你會在其他程序中看到,我們這里不需要。一旦創(chuàng)建了狀態(tài)機,就可以使用 active 方法啟動和停止?fàn)顟B(tài)機,1 表示啟動,0 表示停止。

在我們的循環(huán)中,我們循環(huán)三個不同的狀態(tài)機。

一個真實的例子

讓我們通過一個實際示例來看看使用 PIO 的方法。WS2812B LED 燈條是一種包含三個 LED(一個紅色、一個綠色、一個藍色)和一個小型微控制器的燈組。它們由一根數(shù)據(jù)線控制,帶有計時相關(guān)協(xié)議。
LED 的接線很簡單,可能有一個插座,可以把頭部電線推進去,或者你可能需要自己焊接它們。

你需要注意的是從 Pico 上的 5V 引腳獲得的功率是有限的,如果無限擴展這個燈條,則需要額外給燈條供電。

5cf26ab8-82bb-11ee-939d-92fbcf53809c.png

現(xiàn)在我們已經(jīng)把燈條和 Pico 連接好了,讓我們看看如何用 PIO 來控制它:

import array, time
from machine import Pin
import rp2
from rp2 import PIO, StateMachine, asm_pio


# Configure the number of WS2812 LEDs.
NUM_LEDS = 10


@asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
  T1 = 2
  T2 = 5
  T3 = 3
  label("bitloop")
  out(x, 1).side(0)[T3 - 1]
  jmp(not_x, "do_zero").side(1)[T1 - 1]
  jmp("bitloop").side(1)[T2 - 1]
  label("do_zero").side(0)[T2 - 1]
  nop()


# Create the StateMachine with the ws2812 program, outputting on Pin(22).
sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(0))


# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)

它的基本邏輯是每秒發(fā)送 800,000 位數(shù)據(jù)(注意頻率是 8000000,程序的每個周期是 10 個時鐘周期)。每一位數(shù)據(jù)都是一個脈沖——一個短脈沖表示 0,一個長脈沖表示 1。這個程序和我們之前的 程序之間的一個很大的區(qū)別是,MicroPython 需要能夠向這個程序發(fā)送數(shù)據(jù) PIO 的程序。

數(shù)據(jù)進入狀態(tài)機有兩個階段。第一個是稱為先進先出(FIFO)的內(nèi)存。這是我們的主 Python 程序發(fā)送數(shù)據(jù)到的地方。第二個是輸出移位寄存器(OSR)。這就是 out() 指令獲取數(shù)據(jù)的地方。兩者通過拉指令連接,拉指令從 FIFO 獲取數(shù)據(jù)并將其放在 OSR 中。然而,由于我們的程序設(shè)置了啟用 autopull 的閾值為 24,所以每次我們從 OSR 讀取 24 位時,它將從 FIFO 重新加載指令 out(x,1) 從 OSR 中獲取一位數(shù)據(jù),并將其放入名為 x 的變量中(PIO 中只有兩個可用變量:x 和 y)。

jmp 指令告訴代碼直接移動到特定的標(biāo)簽,但是它可以有一個條件。指令 jmp(not_x,”do_zero”) 告訴代碼,如果 x 的值為 0(或者,在邏輯術(shù)語中,如果 not_x 為真,并且 not_x 是 x 的 反面——在 pio 級別中,0 為假,任何其他數(shù)字為真),則移動到 do_zero。

這里我們一直忽略的一個方面是 .side() 位。它們與 set() 類似,但它們與另一條指令同時發(fā)生。這意味著 out(x,1) 發(fā)生時,.side(0) 設(shè)置側(cè)集引腳的值為 0。

哇,對于這么小的一個程序來說,這實在是太多了?,F(xiàn)在我們已經(jīng)激活了它,讓我們看看如何使用它。下面的代碼需要在程序中位于上述代碼之下,以便將數(shù)據(jù)發(fā)送到 PIO 程序。

# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])


print("blue")
for j in range(0, 255):
  for i in range(NUM_LEDS):
    ar[i] = j
  sm.put(ar,8)
  time.sleep_ms(100)


print("red")
for j in range(0, 255):
  for i in range(NUM_LEDS):
    ar[i] = j<<8
  sm.put(ar,8)
  time.sleep_ms(100)


print("green")


for j in range(0, 255):
  for i in range(NUM_LEDS):
    ar[i] = j<<16
  sm.put(ar,8)
  time.sleep_ms(100)


print("white")
for j in range(0, 255):
  for i in range(NUM_LEDS):
    ar[i]=j<<16+j<<8+j
  sm.put(ar,8)
  time.sleep_ms(100)

在這里,我們跟蹤一個名為 ar 的數(shù)組,它保存了我們希望 LED 擁有的數(shù)據(jù)。數(shù)組中的每個數(shù)字都包含了一盞燈上所有三種顏色的數(shù)據(jù)。格式有點奇怪,因為它是二進制的。使用 PIO 的一個問題是,你經(jīng)常需要處理單個數(shù)據(jù)位。每一位數(shù)據(jù) 都是 1 或 0,數(shù)字可以通過這種方式建立,所以以 10 為基數(shù)的 2 就是二進制的 10。以 10 為基數(shù)的 3 在二進制中等于 11。二進制數(shù)的 8 位中最大的數(shù)是 11111111,或者以 10 為基數(shù)的 255。我們不會在這里深入討論二進制。讓人更困惑的是,我們實際上把三個數(shù)字存儲在一個數(shù)字中。這是因為在 MicroPython 中,整數(shù)存儲在 32 位,但每個數(shù)字只需要 8 位。最后還有一點空閑空間,因為我們只需要 24 位,不過沒關(guān)系。

前八位是藍色,后八位是紅色,最后八位是綠色。8 位最多可以存儲 255 個數(shù)字,所以每個 LED 都有 255 個亮度級別。我們可以使用移位運算符 << 來實現(xiàn)這一點。這將在一個數(shù)字的末尾加上一 定數(shù)量的 0,所以如果我們想讓 LED 的紅色、綠色和藍色亮度達到 1 級,我們將每個值都設(shè)為 1,然后將它們移動到合適的位數(shù)。對于綠色,我們有:

1 << 16 = 10000000000000000

對于紅色,我們有:

1 << 8 = 100000000

對于藍色,我們根本不需要移位位,所以我們只有 1。如果我們把所有這些加在一起, 我們得到以下(如果我們把前面的位加起來,得到一個 24 位的數(shù)):

000000010000000100000001

最右邊的八位是藍色的,接下來的八位是紅色的,最左邊的八位是綠色的。最后一點可能看起來有點令人困惑的是這行:

ar = array.array("I", [0 for _ in range(NUM_LEDS)])

這創(chuàng)建了一個數(shù)組,第一個值是 I,然后每個 LED 都是 0。在開頭有一個I的原因是它告訴 MicroPython 我們使用的是一系列 32 位的值。但是,對于每個值,我們只需要將 24 位發(fā)送給 PIO,所以我們告訴 put 命令刪除 8 位:

sm.put(ar,8)

相關(guān)說明

PIO 狀態(tài)機使用的語言非常簡潔,所以只有少量的指令。除了我們已經(jīng)看過的,你還可以使用:
in():移動 1 到 32 位到狀態(tài)機)與out()類似,但相反)。
push():將數(shù)據(jù)發(fā)送到連接狀態(tài)機和主存的內(nèi)存中 MicroPython 程序。
pull():從連接狀態(tài)機和主存的內(nèi)存塊中獲取數(shù)據(jù) MicroPython 程序。這里我們沒有使用它,因為通過在程序中包含 autopull=True,當(dāng)我們使用 out() 時,會自動發(fā)生這種情況。
mov():在兩個位置之間移動數(shù)據(jù)(例如 x 和 y 變量)。
irq():控制中斷。如果你需要觸發(fā)一個特定的東西以在程序的 MicroPython 端運行,就可以使用這些。
wait():暫停直到發(fā)生一些事情(例如 IO pin 更改了一個設(shè)定值或中斷發(fā)生)。

雖然只有少量的指令,但可以實現(xiàn)大量的通信協(xié)議。大多數(shù)指令都是用于以某種形式移動數(shù)據(jù)。如果你需要以任何特定的方式準(zhǔn)備數(shù)據(jù),例如操縱你希望 LED 的顏色,這應(yīng)該在你的主 MicroPython 程序中完成,而不是在 PIO 程序中。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 微控制器
    +關(guān)注

    關(guān)注

    48

    文章

    7464

    瀏覽量

    150876
  • 狀態(tài)機
    +關(guān)注

    關(guān)注

    2

    文章

    491

    瀏覽量

    27461
  • I2C協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    26

    瀏覽量

    8451
  • 樹莓派
    +關(guān)注

    關(guān)注

    116

    文章

    1696

    瀏覽量

    105457

原文標(biāo)題:樹莓派 Pico 之可編程 IO(PIO)

文章出處:【微信號:趣無盡,微信公眾號:趣無盡】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    樹莓Pico RP2040上怎樣使用MicroPython?

    RP2040 是一款由樹莓公司設(shè)計的 32 位雙核 ARM Cortex-M0+ 微控制器芯片,于 2021 年 1 月發(fā)布,作為樹莓 Pico
    的頭像 發(fā)表于 11-08 14:29 ?3053次閱讀
    在<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b> RP2040上怎樣使用MicroPython<b class='flag-5'>呢</b>?

    樹莓pico入門學(xué)習(xí)筆記(一)相關(guān)資料推薦

    樹莓pico入門學(xué)習(xí)筆記選擇自己熟悉的編程語言樹莓pico提供C/C++和micropyth
    發(fā)表于 07-01 09:28

    樹莓pico如何入門?

    樹莓pico如何入門?
    發(fā)表于 10-13 08:11

    樹莓Pico的相關(guān)資料分享

    關(guān)注、星標(biāo)公眾號,直達精彩內(nèi)容1月22日,樹莓基金會最新發(fā)布一款低成本、高性能的微控制器開發(fā)板Raspberry Pi Pico,新產(chǎn)品相比普通樹莓
    發(fā)表于 11-03 08:44

    樹莓Pico的相關(guān)資料推薦

    1月22日,樹莓基金會最新發(fā)布一款低成本、高性能的微控制器開發(fā)板Raspberry Pi Pico,新產(chǎn)品相比普通樹莓體積更小,售價僅4
    發(fā)表于 02-07 07:37

    樹莓也出MCU了?樹莓Pico來了!

    關(guān)注、星標(biāo)公眾號,直達精彩內(nèi)容1月22日,樹莓基金會最新發(fā)布一款低成本、高性能的微控制器開發(fā)板Raspberry Pi Pico,新產(chǎn)品相比普通樹莓
    發(fā)表于 10-28 10:36 ?11次下載
    <b class='flag-5'>樹莓</b><b class='flag-5'>派</b>也出MCU了?<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b>來了!

    樹莓不講武德,自研雙核MCU Pico,STM32哭暈在廁所!

    PIO架構(gòu),能否開創(chuàng)MCU市場全新領(lǐng)域,STM,兆易創(chuàng)新,STC,全志,樂鑫等一票國產(chǎn)MCU能否跟上?樹莓派發(fā)布雙核基于M0的MCU近日,樹莓派發(fā)布了自研的40nm雙核MCU,嵌入式MCU市場又要迎來真正的新氣象.一如之前發(fā)布的
    發(fā)表于 10-28 20:20 ?14次下載
    <b class='flag-5'>樹莓</b><b class='flag-5'>派</b>不講武德,自研雙核MCU <b class='flag-5'>Pico</b>,STM32哭暈在廁所!

    樹莓Pico:僅4美元的MCU

    1月22日,樹莓基金會最新發(fā)布一款低成本、高性能的微控制器開發(fā)板Raspberry Pi Pico,新產(chǎn)品相比普通樹莓體積更小,售價僅4
    發(fā)表于 12-04 13:06 ?13次下載
    <b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b>:僅4美元的MCU

    樹莓pico入門學(xué)習(xí)筆記(一)

    樹莓pico入門學(xué)習(xí)筆記選擇自己熟悉的編程語言樹莓pico提供C/C++和micropyth
    發(fā)表于 12-17 18:42 ?21次下載
    <b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>pico</b>入門學(xué)習(xí)筆記(一)

    距離檢測報警使用樹莓Pico

    電子發(fā)燒友網(wǎng)站提供《距離檢測報警使用樹莓Pico.zip》資料免費下載
    發(fā)表于 11-09 11:49 ?0次下載
    距離檢測報警使用<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b>

    基于樹莓pico的可編程游戲手柄設(shè)計

    方案介紹組件12x12x7.3mm 瞬時觸覺按鈕按鈕樹莓Pico通用 D1286464 OLED 顯示屏操縱桿模塊 PS210 歐姆電阻?組裝將樹莓
    發(fā)表于 12-26 15:10 ?0次下載

    使用樹莓Pico制作USB麥克風(fēng)

    本指南將教你如何使用樹莓 Pico 和外部數(shù)字麥克風(fēng)制作屬于自己的 USB 麥克風(fēng)。本項目通過 RP2040 微控制器(MCU)的編程 I/O(PIO)、直接存儲器訪問(DMA)和通
    的頭像 發(fā)表于 08-17 10:12 ?2797次閱讀
    使用<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b>制作USB麥克風(fēng)

    樹莓PICO pio使用

    樹莓 Pico 小小的板子上總是能讓我們發(fā)現(xiàn)一些驚喜。其所使用的RP2040芯片還具備8個可編程I/O(PIO)狀態(tài)機,用于自定義外圍設(shè)備
    的頭像 發(fā)表于 10-18 15:17 ?1491次閱讀

    樹莓Pico Flash驅(qū)動踩坑記錄

    樹莓 pico 帶有 2MB 的 Flash 資源,以下是我基于官方 Pico C/C++ SDK 對接 Flash 驅(qū)動時踩到的一些坑和解決辦法。
    的頭像 發(fā)表于 10-20 11:44 ?1452次閱讀

    如何在樹莓Pico上使用紅外線接收模塊?

    樹莓 Pico 上使用紅外線接收模塊(HX1838 型),我們采用開源的 pico_ir 庫。
    的頭像 發(fā)表于 11-30 09:08 ?2079次閱讀
    如何在<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>Pico</b>上使用紅外線接收模塊?