3.19. UART a kódban

A machine.UART egyetlen hardveres UART-csatornát fog be. Hozz létre egyet a busz azonosítójával és egy átviteli sebességgel; minden másnak ésszerű alapértéke van:

from machine import UART

uart = UART(3, baudrate=115200)

Az id választja ki, melyik hardveres UART-ot használd; az érték a paneltől függ (lásd a OpenMV kártyák oldalt az adott kamerán elérhető buszszámokért és lábkiosztásokért). Az alapértelmezett keretformátum 8 adatbit, paritás nélkül, egy stop bit – a mindenki által várt „8N1”.

3.19.1. Írás és olvasás

A UART-kimenet a write() metóduson keresztül megy:

uart.write("hello\n")
uart.write(b"\x01\x02\x03")

A write elfogad egy str-t (UTF-8 kódolással) vagy egy bytes / bytearray objektumot. Azonnal visszatér, amint a bájtok bekerülnek a TX-pufferbe; a hardver a háttérben fejezi be a kiléptetésüket.

Az olvasás három metóduson keresztül történik, attól függően, mire van szükség:

n = uart.any()              # bytes available to read right now
data = uart.read(8)         # up to 8 bytes, or None on timeout
line = uart.readline()      # bytes ending in '\n', or None on timeout

A any() blokkolás nélkül ellenőrzi az RX-puffert. A read() fix számú bájtot olvas, és None-t ad vissza, ha előbb lejár az időkorlát (a konstruktor timeout argumentumával állítható). A readline() a következő sortörésig (azt is beleértve) olvas, ami hasznos a sorokra épülő protokolloknál.

Egy egyszerű ciklus, amely visszhangozza mindazt, amit kap:

uart = UART(3, baudrate=115200, timeout=100)

while True:
    if uart.any():
        data = uart.read()
        uart.write(data)

A read() hosszargumentum nélkül addig olvas bájtokat, amíg a vételi vonal a beállított timeout ideig csendben nem marad, majd visszaadja az addig összegyűjtötteket. timeout=100 esetén minden hívás egy adatcsomagot (burst) ad vissza – mindent, amit a küldő 100 ms-nál nagyobb bájtok közötti szünet nélkül kiléptetett. Időkorlát nélkül a hívásnak nem lenne jele arról, hogy a küldő végzett, és határozatlan ideig fennakadhatna.

3.19.2. Bináris adat struct-tal

Egész számok és lebegőpontos értékek vezetéken keresztüli küldéséhez való a struct modul. Fix szélességű értékeket csomagol egy bytes objektumba egy formátumsztring segítségével, amely megnevezi a bájtsorrendet és az egyes mezők típusát:

import struct

uart.write(struct.pack("<lhb", count, temperature_x100, status))

A bevezető "<" little-endian bájtsorrendet választ; az "l" 32 bites előjeles egész, a "h" 16 bites előjeles egész, a "b" 8 bites előjeles egész. A másik oldal ugyanazzal a formátumsztringgel csomagolja ki:

payload = uart.read(7)        # 4 + 2 + 1 = 7 bytes
count, temperature_x100, status = struct.unpack("<lhb", payload)

A formátumsztring a két vég közötti szerződés. Bármilyen eltérés – rossz bájtsorrend, rossz típusméretek, rossz mezősorrend – értelmetlen értékeket eredményez.

3.19.3. Pufferelés és nagy sebességű olvasások

Egy lekérdező ciklus, amely a any() és read() metódusokat hívja, magától lépést tart a legtöbb forgalommal, amíg a fő ciklus elég gyorsan iterál ahhoz, hogy a vételi puffert kiürítse, mielőtt megtelne. Két konstruktoropció számít, amikor a sebesség megnő vagy a ciklus elfoglalt.

Az rxbuf a szoftveres RX-puffer méretét állítja be. Az alapérték néhány száz bájt; olyan érzékelőknél, amelyek adatcsomagonként több száz bájtot bocsátanak ki, vagy amikor a fő ciklus hosszú munkát végez a lekérdezések között, a puffer megnövelése megakadályozza a beérkező bájtok eldobását, miközben a ciklus máshol van elfoglalva:

uart = UART(3, baudrate=115200, timeout=100, rxbuf=4096)

Bármi, ami a puffer telítettsége alatt érkezik, elvész; méretezd az rxbuf-ot úgy, hogy lefedje a kiürítések közötti leghosszabb szünetet.

Tartós nagy sebességekhez a readinto() egy előre lefoglalt pufferbe olvas, ahelyett hogy minden híváskor egy új bytes objektumot adna vissza:

buf = bytearray(256)

while True:
    n = uart.readinto(buf)
    if n:
        process(buf, n)

Az olvasási útvonalon nem történik memóriafoglalás, ami akkor számít, amikor a halom fragmentált, vagy amikor a foglalás késleltetése egyébként túllökné a bájtok közötti időzítési keretet.