3.19. UART u kodu¶
machine.UART omata jedan hardverski UART kanal. Konstruirajte ga s id-om sabirnice i brzinom prijenosa; sve ostalo ima razumne zadane vrijednosti:
from machine import UART
uart = UART(3, baudrate=115200)
id odabire koji hardverski UART koristiti; vrijednost ovisi o pločici (pogledajte OpenMV ploče za dostupne brojeve sabirnica i raspored pinova na danoj kameri). Zadani format okvira je 8 podatkovnih bitova, bez pariteta, jedan stop bit – „8N1” koji svi očekuju.
3.19.1. Pisanje i čitanje¶
UART izlaz prolazi kroz write():
uart.write("hello\n")
uart.write(b"\x01\x02\x03")
write prihvaća ili str (kodiran kao UTF-8) ili bytes / bytearray. Vraća se odmah čim su bajtovi stavljeni u red u TX međuspremniku; hardver u pozadini dovršava njihovo isijavanje.
Čitanja se odvijaju kroz tri metode, ovisno o tome što je potrebno:
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
any() provjerava RX međuspremnik bez blokiranja. read() čita fiksni broj bajtova, vraćajući None ako prvo istekne vremensko ograničenje (podesivo putem argumenta timeout u konstruktoru). readline() čita do sljedećeg znaka novog retka uključujući njega, što je korisno za protokole temeljene na retcima.
Jednostavna petlja koja odjekuje sve što primi:
uart = UART(3, baudrate=115200, timeout=100)
while True:
if uart.any():
data = uart.read()
uart.write(data)
read() bez argumenta duljine nastavlja čitati bajtove sve dok prijemna linija ne ostane tiha tijekom konfiguriranog timeout-a, zatim vraća sve što je akumulirano. S timeout=100 svaki poziv ovdje vraća jednu rafalu bajtova – sve što je pošiljatelj isijao bez razmaka od 100 ms između bajtova. Bez vremenskog ograničenja poziv ne bi imao signal da je pošiljatelj gotov i mogao bi se zaglaviti na neodređeno vrijeme.
3.19.2. Binarni podaci sa struct¶
Slanje cijelih brojeva i decimalnih brojeva preko žice ono je za što je modul struct namijenjen. On pakira vrijednosti fiksne širine u bytes objekt koristeći format niz koji imenuje redoslijed bajtova i tip svakog polja:
import struct
uart.write(struct.pack("<lhb", count, temperature_x100, status))
Vodeći "<" bira little-endian redoslijed bajtova; "l" je 32-bitni cijeli broj s predznakom, "h" je 16-bitni cijeli broj s predznakom, "b" je 8-bitni cijeli broj s predznakom. Druga strana raspakira istim format nizom:
payload = uart.read(7) # 4 + 2 + 1 = 7 bytes
count, temperature_x100, status = struct.unpack("<lhb", payload)
Format niz je ugovor između dvije strane. Bilo kakvo neslaganje – pogrešan redoslijed bajtova, pogrešne veličine tipova, pogrešan redoslijed polja – proizvodi besmislene vrijednosti.
3.19.3. Međuspremanje i čitanja pri visokoj brzini¶
Petlja prozivanja koja poziva any() i read() sama prati većinu prometa, sve dok glavna petlja iterira dovoljno brzo da isprazni prijemni međuspremnik prije nego što se napuni. Dvije opcije konstruktora su važne kada brzina raste ili je petlja zauzeta.
rxbuf postavlja veličinu softverskog RX međuspremnika. Zadana vrijednost je nekoliko stotina bajtova; za senzore koji emitiraju stotine bajtova po rafali, ili kada glavna petlja obavlja dug posao između prozivanja, povećavanje međuspremnika sprječava ispuštanje dolaznih bajtova dok je petlja zauzeta drugdje:
uart = UART(3, baudrate=115200, timeout=100, rxbuf=4096)
Sve što stigne dok je međuspremnik pun je izgubljeno; dimenzionirajte rxbuf da pokrije najduži razmak između pražnjenja.
Za održive visoke brzine, readinto() čita u unaprijed dodijeljeni međuspremnik umjesto vraćanja svježeg bytes objekta pri svakom pozivu:
buf = bytearray(256)
while True:
n = uart.readinto(buf)
if n:
process(buf, n)
Na putu čitanja ne događa se nikakvo dodjeljivanje memorije, što je važno kada je gomila fragmentirana ili kada bi kašnjenje dodjeljivanja inače prešlo vremenski proračun između bajtova.