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.