Hempl/PIO
PIO 代表可程式設計輸入/輸出,這是控制和測量連線到匯流排聯結器的 AVR32 處理器引腳上的數字電壓電平的最簡單方法。
要將 GPIO 引腳用作 PIO,您必須首先將引腳設定為輸入或輸出。如果將其設定為輸入,則可以檢查輸入電壓以檢視它是否具有傳入的低電平或高電平,例如檢查開關的位置。如果將其設定為輸出,則可以對其程式設計以輸出低電壓或高電壓以控制燈光、電機或其他電路。
對於作為輸入的 PIO 引腳,您還可以要求當該引腳上的電壓從 0 變為 1 或從 1 變為 0 時,這將產生一箇中斷。發生這種情況時,處理器將停止其正在執行的操作,執行一個稱為中斷例程的特殊程式碼段,並在完成該操作後,它將返回並繼續其在中斷髮生時正在執行的操作。
最後,每個引腳都有一個可選的上拉電阻,可以啟用它,以便如果沒有任何東西連線到作為輸入的引腳,它將浮動到邏輯“1”而不是隨機波動。這是連線開關或按鈕的常用方法:您在引腳上程式設計一個上拉電阻,然後將開關連線到引腳和零伏之間,以便當觸點閉合時,您將讀取 0 的值,而當觸點開啟時,您將讀取 1 的值。
AT32UC3A 晶片的任何外設引腳都可以讀取為數字輸入或設定為輸出,並程式設計為 0 或 1 邏輯電平。
當引腳設定為輸出時,0 邏輯輸出將引腳連線到 0 伏,而邏輯 1(“高”)值將 3.3 伏放在它上面,兩種狀態的最大電流供應或消耗為 4 毫安。
當它們被設定為輸入時,從 0.0 到 0.8 伏的電壓電平讀取為“0”(低)輸入,而從 2.0 伏到 5.0 伏的電壓電平讀取為“1”(高)輸入。從 0.8 到 2.0 伏的值可能讀取為高或低,不確定。
Mizar32 的一些引腳只能用作可程式設計 I/O 引腳,因為它們沒有用於其他任何用途。其他引腳將訊號傳送到各種外圍裝置,但是,如果這些裝置沒有被使用,則可以使用這些引腳作為 PIO 引腳。
其他引腳對於處理器的正常執行至關重要,例如用於訪問 SDRAM、振盪器和其他板載電路的那些引腳;如果您將它們用作 PIO 引腳,則板很可能會崩潰,需要按下其復位按鈕。
| 引腳 | 名稱 | 匯流排引腳 | PicoLisp |
|---|---|---|---|
| PA2 | GPIO2 | BUS5 引腳 11 | 'PA_2
|
| PA7 | GPIO7 | BUS5 引腳 12 | 'PA_7
|
| PB17 | GPIO49 | BUS5 引腳 8 | 'PB_17
|
| PB18 | GPIO50 | BUS5 引腳 9 | 'PB_18
|
| PB29 | GPIO61 | 板載 LED | 'PB_29
|
| PB30 | GPIO62 | BUS6 引腳 9 | 'PB_30
|
| PB31 | GPIO63 | BUS6 引腳 10 | 'PB_31
|
| PX16 | GPIO88 | 使用者按鈕 | 'PX_16
|
| PX19 | GPIO85 | BUS6 引腳 12 | 'PX_19
|
| PX22 | GPIO82 | BUS6 引腳 11 | 'PX_22
|
| PX33 | GPIO71 | BUS5 引腳 10 | 'PX_33
|
未使用的 ADC、PWM、SPI 或 UART 引腳也可以用作 PIO 引腳。有關相關引腳名稱,請參見這些部分。這將可用的 PIO 總數增加到 66 個。
PIO Hempl 模組允許您將任何引腳設定為邏輯輸入或將其設定為輸出,並在其上放置 0v 或 3.3V,並且您可以在任何引腳上啟用上拉電阻。
此示例點亮板載 LED。
來自 PicoLisp
(setq led 'PB_29) (pio-pin-setdir *pio-output* led) (pio-pin-setlow led)
請注意,在復位後,LED 在第 2 行亮起,因為復位狀態是所有引腳都為低電平,並且當訊號為低電平時,板載 LED 亮起。要設定一個初始值為高的輸出引腳,您需要在呼叫 pio.pin.setdir() 之前呼叫 pio.pin.sethigh()。
這是一個讀取一個 PIO 引腳並驅動另一個引腳以響應它的示例。我們將讀取連線到板載使用者按鈕的引腳,並且只要按下該按鈕,我們就將使板載 LED 閃爍。在 PicoLisp 中,以下是如何操作。
# A simple program which demonstrates
# the usage of user-buttons.
# declare pins
(setq led 'PB_29 button 'PX_16)
# a simple delay function
(de delay (t)
(tmr-delay 0 t) )
# make sure the LED starts in
# the "off" position and enable
# input/output pins
(de init-pins ()
(pio-pin-sethigh led)
(pio-pin-setdir *pio-output* led)
(pio-pin-setdir *pio-input* button) )
# And now, the main loop
(de prog-loop ()
(init-pins)
(loop
(if (= 0 (pio-pin-getval button))
(prog (pio-pin-setlow led)
(delay 100000)
(pio-pin-sethigh led)
(delay 100000) ) ) ) )
(prog-loop)
使用者按鈕的電路非常簡單:按下按鈕時,它將 PIO 引腳連線到零伏,提供低輸入值,並且在 PIO 引腳和 3.3 伏之間有一個電阻,以便如果按鈕沒有被按下,PIO 引腳將輕輕地拉到 3.3V 並讀取為高值。
其他未連線到任何東西的 PIO 引腳,如果您將它們程式設計為輸入,將拾取周圍環境的隨機噪聲,並給出有時為高有時為低的值。可程式設計上拉電阻是一種確保如果沒有任何訊號連線到輸入引腳,它將被輕輕地拉到高值而不是隨機漂浮的方法。
此示例將一個未使用的 GPIO 引腳轉換為 PIO 輸入,但確保如果沒有任何東西物理連線到它,它將始終返回高值 1。
如果您從以下程式碼中刪除 (pio-pin-setpull) 行(至少在我的測試板上),它會列印大部分為零,但如果您觸控 Mizar32 板的底部,則值會在 0 和 1 之間閃爍。包含 (pio-pin-setpull) 行,除非您用一段電線將其連線到 GND 引腳(例如 BUS5 引腳 14),否則輸入值始終為 1。
在 PicoLisp 中
(setq pin 'PA_2) # Stabilize GPIO2 (connector BUS5 pin 11) (pio-pin-setdir *pio-input* pin) (pio-pin-setpull *pio-pullup* pin) (loop (prinl (pio-pin-getval pin)) )
雖然 Hempl 也有類似的原始函式 PULLDOWN,但 Mizar32 中使用的 AVR32 晶片在其硬體中沒有可程式設計下拉電阻,因此使用它會引發錯誤訊息。
要再次停用上拉電阻,您可以使用
(pio-pin-setpull pin *pio-nopull*)
可程式設計上拉電阻的另一個用途是實現“開集輸出”。在這種方案中,引腳可以處於兩種狀態之一:要麼它被驅動為 0 輸出,要麼它被讀取為輸入。上拉電阻確保如果沒有人將其驅動為輸出,每個人都會將其讀取為高值。當多臺計算機需要透過一根訊號線進行通訊,並且任何一臺計算機都可以與任何其他計算機通訊,而無需主從關係或協商誰控制匯流排的方式時,就會使用它。使用這種系統,任何計算機都可以讀取電線以檢視其值是高還是低,任何計算機都可以將電線驅動到低值,以便所有其他計算機讀取它。這與將電線驅動為高或低輸出不同,因為如果一臺計算機將其驅動為高,而另一臺計算機將其驅動為低,則可能會損壞相關計算機,並且肯定會導致通訊混亂。
一個簡單的例子是,一個系統可以透過多個開關單元中的任何一個來開啟或關閉房屋的燈光。而 I2C 匯流排是一個更高階的例子,它在訊號線上使用開集輸出,這樣 I2C 總線上的任何一臺計算機都可以與任何其他計算機通訊,而不會在匯流排線上產生衝突的訊號。
以下程式碼在 PIO 引腳上實現了一個開集輸出,提供了一個函式將其配置為 OC 引腳,一個函式將其驅動為低輸出,還有一個函式將其設定為輸入並告訴你此時導線上是什麼值。
在 PicoLisp 中
# Turn a PIO pin into an open-collector output. # Call this function once before using the other # two to drive and read the pin. (de oc-setup (pin) # OC output starts as an input, not driving # the bus wire (pio-pin-setdir *pio-input* pin) # Arrange that, when it is an input and no # one is driving it, it will float high (pio-pin-setpull *pio-pullup* pin) # and that when we set it as an output, it will drive a low value (pio-pin-setlow pin) ) # Drive a low output value onto the pin. # The low output value is already programmed during setup() # so we only need to enable it as an output. (de oc-drive-low (pin) (pio-pin-setdir *pio-output* pin) ) # Make the pin an input and return the value on the bus wire (de oc-read (pin) (pio-pin-setdir *pio-input* pin) (pio-pin-getval pin) )
請注意:目前 PicoLisp 不支援中斷處理。請參閱 問題 #2。
像 'PB_29 這樣的符號會返回 Hempl 內部用來識別 GPIO 引腳的數字。除了在一種情況下,你不需要知道這些數字的值:當你同時從 Hempl 在不同的 GPIO 引腳上啟用了多個邊沿觸發中斷。
如果你想將像 'PB_29 這樣的符號解碼為埠號和引腳號,你可以使用
(pio-decode 'PB_29)
結果是一個列表。它的 car 給出埠號,它的 cadr 給出引腳號。
對於埠 A 上的引腳,port 將為 0,pin 將為 0 到 31 之間的數字。
對於埠 B 上的引腳,port 將為 1,pin 將為 0 到 31 之間的數字。
對於埠 C 上的引腳,port 將為 2,pin 將為 0 到 5 之間的數字。
對於埠 X 上的引腳,port 將為 23,pin 將為 0 到 39 之間的數字。
- 維基百科上的 開集 文章
- Atmel AT32UC3A 資料手冊 第 22 章:通用輸入/輸出控制器 (GPIO)