3.19. UART koodissa

machine.UART kääräisee yhden laitteistollisen UART-kanavan. Luo se väylän id:llä ja siirtonopeudella; kaikella muulla on järkevät oletukset:

from machine import UART

uart = UART(3, baudrate=115200)

id valitsee, mitä laitteistollista UART:ia käytetään; arvo riippuu levystä (katso OpenMV-kortit saadaksesi käytettävissä olevat väylänumerot ja nastamääritykset tietyllä kameralla). Oletuskehysmuoto on 8 databittiä, ei pariteettia, yksi lopetusbitti – kaikkien odottama ”8N1”.

3.19.1. Kirjoittaminen ja lukeminen

UART-ulostulo kulkee metodin write() kautta:

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

write hyväksyy joko str-arvon (koodattuna UTF-8:ksi) tai bytes- / bytearray-arvon. Se palaa heti, kun tavut on jonotettu TX-puskuriin; laitteisto kellottaa ne ulos loppuun taustalla.

Lukeminen tapahtuu kolmella metodilla sen mukaan, mitä tarvitaan:

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() tarkistaa RX-puskurin estämättä. read() lukee kiinteän määrän tavuja palauttaen None, jos aikakatkaisu (säädettävissä konstruktorin timeout-argumentilla) umpeutuu ensin. readline() lukee seuraavaan rivinvaihtoon asti se mukaan lukien, mikä on hyödyllistä riveihin perustuville protokollille.

Yksinkertainen silmukka, joka kaiuttaa vastaanottamansa:

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

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

read() ilman pituusargumenttia jatkaa tavujen lukemista, kunnes vastaanottolinja pysyy hiljaisena määritetyn timeout-ajan, ja palauttaa sitten kertyneen sisällön. Arvolla timeout=100 kukin kutsu palauttaa yhden tavujen purskeen – kaiken, minkä lähettäjä kellotti ulos ilman 100 ms:n väliä tavujen kesken. Ilman aikakatkaisua kutsulla ei olisi merkkiä siitä, että lähettäjä on valmis, ja se voisi jumiutua loputtomiin.

3.19.2. Binääridata structilla

Kokonaislukujen ja liukulukujen lähettäminen linjan yli on juuri sitä, mitä varten struct -moduuli on. Se pakkaa kiinteäleveyksiset arvot bytes-objektiksi muotomerkkijonon avulla, joka nimeää tavujärjestyksen ja kunkin kentän tyypin:

import struct

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

Aloittava "<" valitsee little-endian-tavujärjestyksen; "l" on 32-bittinen etumerkillinen kokonaisluku, "h" on 16-bittinen etumerkillinen kokonaisluku, "b" on 8-bittinen etumerkillinen kokonaisluku. Toinen puoli purkaa pakkauksen samalla muotomerkkijonolla:

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

Muotomerkkijono on kahden pään välinen sopimus. Mikä tahansa ristiriita – väärä tavujärjestys, väärät tyyppikoot, väärä kenttäjärjestys – tuottaa järjettömiä arvoja.

3.19.3. Puskurointi ja korkeataajuiset luvut

Pollaava silmukka, joka kutsuu metodeja any() ja read(), pysyy itsekseen mukana suurimmassa osassa liikennettä, kunhan pääsilmukka iteroi tarpeeksi nopeasti tyhjentääkseen vastaanottopuskurin ennen kuin se täyttyy. Kaksi konstruktorin valitsinta merkitsevät, kun nopeus nousee tai silmukka on kiireinen.

rxbuf asettaa ohjelmistollisen RX-puskurin koon. Oletus on muutama sata tavua; sensoreille, jotka lähettävät satoja tavuja purskeessa, tai kun pääsilmukka tekee pitkää työtä pollausten välissä, puskurin suurentaminen estää saapuvien tavujen katoamisen, kun silmukka on muualla kiireinen:

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

Kaikki, mikä saapuu puskurin ollessa täynnä, häviää; mitoita rxbuf kattamaan pisin väli tyhjennysten välillä.

Jatkuviin korkeisiin nopeuksiin readinto() lukee esivaratuun puskuriin sen sijaan, että se palauttaisi tuoreen bytes-objektin joka kutsulla:

buf = bytearray(256)

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

Lukupolulla ei tapahdu varauksia, mikä merkitsee, kun keko on pirstoutunut tai kun varausviive muuten työntäisi tavujen välisen ajoitusbudjetin yli.