張高興的 MicroPython 入門指南:(三)使用串列埠通訊

张高兴發表於2024-07-22

目錄
  • 什麼是串列埠
  • 使用方法
  • 使用板載串列埠相互通訊
    • 硬體需求
    • 電路
    • 程式碼
  • 使用板載的 USB 串列埠
  • 參考

什麼是串列埠

串列埠是序列介面的簡稱,這是一個非常大的概念,在嵌入式中串列埠通常指 UART(Universal Asynchronous Receiver/Transmitter,通用非同步收發器)。使用串列埠進行的通訊叫做序列通訊,與之相對的一個概念是並行通訊。序列通訊是指資料一位一位的按順序傳輸,而並行通訊則是多位資料同時傳輸。如下圖所示,DATA BUSUART 1 之間是並行通訊,UART 1UART 2 之間是序列通訊。

串列埠通訊的資料幀格式如下圖所示,通常一幀共包括 10 位:1 個起始位,8 個資料位和 1 個停止位。有一些特殊的資料幀在停止位前面包含 1 位的奇偶校驗位,還有的停止位有 2 個位元。其中起始位為低電平(0),標誌著資料傳輸的開始;停止位為高電平(1),表示資料幀傳輸結束;資料位則為實際傳送的資料,使用高低電平來表示二進位制資訊,如果傳送的內容是文字,那麼這段資料為字元的二進位制編碼(ASCII、UTF-8等)。資料傳輸的速率我們使用波特率(Baud Rate)來表示,即每秒鐘傳送的碼元符號的個數。比如資料傳輸速率為 9600 字元/s,那麼這時的波特率為 9600。

裝置進行串列埠通訊時,裝置的連線如下圖所示,兩個裝置的訊號線,即傳送端(TXD)與接收端(RXD)交叉相連,並且需要共地。在 Raspberry Pi Pico 的引腳上共引出了 2 組串列埠,即 UART0UART1

使用方法

使用 MicroPython 控制 GPIO 要使用 machine 包中的 UART 類。

from machine import UART

透過建構函式例項化獲取串列埠物件。

UART(id: int, baudrate: int = 115200, ...)
  • id 指串列埠的編號。對於 Pico 而言只能是 0 或 1。
  • baudrate 用於設定波特率。
  • txrx 引數指定要使用的 tx、rx 引腳。
  • parity 設定校驗位。None 無,0 偶數,1 奇數。
  • stop 設定停止位的長度。
  • timeout 設定讀取超時時間,單位為毫秒。

使用 init() 方法可以修改串列埠的設定,方法引數與建構函式的引數一致。常見的用法參考下面的例子:

uart0 = UART(0, 9600)   # 例項化串列埠 0,波特率為 9600
uart0.init(115200, bits=8, parity=None, stop=1) # 修改串列埠 0 設定
uart1 = UART(1, baudrate=9600, tx=Pin(8), rx=Pin(9))    # 例項化串列埠 1 並指定引腳

例項化串列埠物件後,使用 write(buf: bytearray) 方法傳送資料,傳送成功會返回位元組數,失敗則返回 None

data = b'hello world'
uart0.write(data)

接收資料使用 read(nbytes: Optional[int] = None) 方法,nbytes 設定接收的位元組數,讀取成功會返回一個位元組物件,讀取超時則返回 None。也可以使用 readline() 方法讀取一行。

data = bytes()
data = uart0.read(10)
print(data.decode('utf-8')) # 解碼成 utf-8 字串
print(uart0.readline()) # 從串列埠讀取一行

有些時候需要判斷串列埠中有沒有資料,可以使用 any() 方法。

while uart0.any() > 0:
    print(uart0.readline())

💡 提示

在部分開發板上可以像 GPIO 中斷一樣,使用串列埠中斷 irq(trigger, priority=1, handler=None, wake=machine.IDLE)

使用 deinit() 方法可關閉串列埠。

uart0.deinit()

使用板載串列埠相互通訊

Pico 上有兩組串列埠 UART0UART1,因此可以使用這兩組串列埠相互通訊。

硬體需求

名稱 數量
杜邦線 若干

電路

  • UART0 RX(GP1) - UART1 TX(GP4)
  • UART0 TX(GP0) - UART1 RX(GP5)

程式碼

from machine import UART, Pin
import utime

# 初始化串列埠
uart0 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
# 串列埠 1 傳送資料
txData = b'hello world'
uart1.write(txData)
utime.sleep_ms(100)
# 串列埠 2 檢測接收資料
rxData = bytes()
while uart0.any() > 0:
    rxData += uart0.read(1)
# 解碼並列印
print(rxData.decode('utf-8'))

使用板載的 USB 串列埠

當 Pico 連線到計算機上時,在裝置管理器中會新增一個通訊埠 COMx,MicroPython 的 REPL 終端就是執行在這個串列埠之上。那麼能使用這個板載 USB 串列埠傳輸資料嗎?答案是可以的,但與正常串列埠通訊的程式碼不同,需要使用 select,一個用於非同步 I/O 多路複用的模組。將下面的程式碼燒錄到 Pico 中,使用 PuTTY 等串列埠工具連線 Pico,當 Pico 檢測到輸入 1 時點亮板載 LED,輸入 0 時熄滅。

import machine
import select
import sys

led = machine.Pin('LED', machine.Pin.OUT)
# 獲取複用的輪詢物件
poll_object = select.poll()
# 將系統標準輸入註冊為輪詢物件
poll_object.register(sys.stdin, 1)

while True:
    # 檢查 USB 串列埠輸入
    if poll_object.poll(0):
        # 從 USB 串列埠中讀取
        ch = sys.stdin.read(1)
        if ch == '1'
            led.value(1)
            # 向 USB 串列埠中寫入
            print("LED ON")
        else
            led.value(0)
            print("LED OFF")

參考

  1. Universal asynchronous receiver-transmitter - Wikipedia:https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter
  2. Serial Communication - Wikipedia:https://en.wikipedia.org/wiki/Serial_communication
  3. BASICS OF UART COMMUNICATION:http://www.circuitbasics.com/basics-uart-communication/
  4. 波特率 - 百度百科:https://baike.baidu.com/item/波特率
  5. MicroPython documentation:https://docs.micropython.org/en/latest/library/machine.UART.html

相關文章