Skip to Content
Lua 自動化GPIO 與 UART

GPIO 與 UART

除了 I2C,腳本還能操作 GPIO 腳位,以及跟 UART 面板互動。GPIO 在模擬後端 (mock)就能跑;UART 需要真的接上會回話的硬體,模擬後端沒有對應的模擬。

gpio.write/gpio.read/gpio.release

gpio.write(0, true) -- 把腳位 0 設成輸出,寫入高電位 local v = gpio.read(0) -- 讀回目前電位:1(高)或 0(低) gpio.write(0, false) -- 寫入低電位;也可以直接寫數字 gpio.write(0, 0) gpio.release(0) -- 交還腳位,讓其他人可以使用
  • gpio.write(腳位, 電位):把腳位設為輸出並寫入電位。電位可以寫 true/false, 也可以直接寫數字(非 0 是高、0 是低)。
  • gpio.read(腳位):讀回目前腳位的電位,回傳 1 或 0。腳位如果之前已經被同一支 腳本 gpio.write() 設成輸出,gpio.read() 讀的就是目前輸出的鎖存值,不用先切回 輸入。
  • gpio.release(腳位):提早把腳位交還,讓其他使用者(其他面板、下一次手動操作) 可以接手。就算不呼叫,腳本結束時(不論通過、失敗、出錯或被中止)程式都會自動 收回這支腳本佔用的全部腳位——gpio.release() 只是給你一個提早釋放的手段,不是 唯一的收尾方式。

⚠ 模擬後端只模擬腳位 0~3:mock 只會回應這四支腳位的讀寫,其餘腳位編號在 mock 上會失敗;真實硬體支援的腳位數依接的裝置而定。

範例:腳位 0~3 輪流輸出高/低並讀回確認

gpio_toggle.lua下載 gpio_toggle.lua
-- GPIO 腳位 0~3 的寫入/讀回/釋放;hal_mock 只模擬這四支腳位。
for pin = 0, 3 do
  gpio.write(pin, true)
  check(gpio.read(pin) == 1, "pin " .. pin .. " reads back high")
  gpio.write(pin, false)
  check(gpio.read(pin) == 0, "pin " .. pin .. " reads back low")
  gpio.release(pin)
end
log("info", "gpio_toggle done")
預期輸出
CHECK OK: pin 0 reads back high
CHECK OK: pin 0 reads back low
CHECK OK: pin 1 reads back high
CHECK OK: pin 1 reads back low
CHECK OK: pin 2 reads back high
CHECK OK: pin 2 reads back low
CHECK OK: pin 3 reads back high
CHECK OK: pin 3 reads back low
gpio_toggle done

uart.write/uart.read/uart.expect:需要真實硬體

uart.write("PING\n") -- 把字串原樣送出 local line = uart.read(2000) -- 等最多 2000ms,等到一行就回傳字串,逾時回傳 nil local line2, num = uart.expect("^PONG (%d+)", 2000) -- 等到就回傳整行+括號比對到的內容,逾時回傳 nil
  • uart.write(字串 [, panel]):原樣送出字串,不會自動加換行。
  • uart.read(逾時毫秒 [, panel]):在時限內等待下一行收到的資料;逾時就回傳 nil,不會讓腳本出錯。
  • uart.expect(樣式, 逾時毫秒 [, panel]):跟 uart.read 一樣等待,但只在等到 「符合樣式」的一行才算數(樣式是 string.find 用的 Lua pattern);等到符合的 行時,第一個回傳值是整行內容,接著是樣式裡每一組括號 (...) 各自比對到的 子字串(沒有括號就只回傳整行),逾時一樣回傳 nil。
  • panel 都是可省略的最後一個參數:目前的分頁如果剛好只開了一個 UART 面板, 省略就是指那一個;開了不只一個(或一個都沒開)就必須自己指定,不然會出錯。
  • ⚠ uart.read/uart.expect 只看得到這支腳本本次執行、第一次呼叫任何一個 uart.* 之後才到達的資料,執行前就已經在面板上的舊資料不算「已經到的」; 該看的資料如果在腳本讀到之前就被覆寫掉,兩者都會出錯提醒你(而不是靜默漏看)。

⚠ uart.* 沒辦法在模擬後端上真的跑:mock 不會模擬任何 UART 裝置的回話, 下面這支範例只用來示範語法,實際執行需要接上一個會回應 PING/PONG 這類約定 的真實裝置。

uart_expect.lua下載 uart_expect.lua
-- 需要真實 UART 硬體才能執行:等待裝置回覆符合特定樣式的一行。
-- (hal_mock 沒有 UART 模擬,本檔只在建置期做語法檢查,不會被實際執行。)
uart.write("PING\n")
local line = uart.expect("^PONG", 2000)
if line == nil then
  fail("no PONG reply within 2000ms")
end
log("info", "uart_expect got: " .. line)

⚠ 這支範例需要實體硬體才能真的執行,模擬後端(mock)沒有對應的裝置可以回應。

接下來

下一頁介紹 dump/dump_all/file.append/timestamp:怎麼把暫存器內容或 自己的訊息留下記錄。