Otázka:
Jak funguje sériová komunikace na Arduinu?
Nick Gammon
2016-01-20 08:45:06 UTC
view on stackexchange narkive permalink

S odkazem na desky Arduino Uno, Mega2560, Leonardo a podobné:

  • Jak funguje sériová komunikace?
  • Jak rychlá je sériová výroba?
  • Jak se mohu spojit mezi odesílatelem a příjemcem?

Poznámka: Toto je zamýšleno jako referenční otázka.

To by vás mohlo zajímat o bufferech na obou stranách Nano připojeného k systému Raspian, na kterém běží datový záznamník Pythonu, pomocí běžného programovacího kabelu USB mezi těmito dvěma: https://arduino.stackexchange.com/questions/11710/does -data-come-on-serial-port-store-for-some-time
Jeden odpovědět:
Nick Gammon
2016-01-20 08:45:06 UTC
view on stackexchange narkive permalink

Asynchronní sériová (obvykle označovaná jako sériová) komunikace se používá k odesílání bajtů z jednoho zařízení do druhého. Zařízení může být jedno nebo více z následujících:

  • Arduino
  • PC
  • GPS
  • čtečka RFID karet
  • LCD displej
  • modem
  • jiné

taktovací frekvence a vzorkování dat

Na rozdíl od SPI / USB / I2C sériová komunikace nemá hodinový signál. Vzorkovací hodiny jsou dohodnutou vzorkovací frekvencí (známou jako přenosová rychlost). Odesílatel i přijímač musí být nakonfigurováni tak, aby používali stejnou rychlost, jinak bude přijímač přijímat nesmyslná data (kvůli tomu, že se bity nevybírají stejnou rychlostí, jakou byly odeslány).

Přenos je asynchronní, což v zásadě znamená, že bajty lze odeslat kdykoli, s různými mezerami mezi nimi. Tato grafika ilustruje odesílaný jeden bajt:

Serial comms - sending one byte

Obrázek výše ukazuje přenášené písmeno „F“. V ASCII je to 0x46 (v hexadecimálním formátu) nebo 0b01000110 (v binárním formátu). Nejprve se vysílá nejméně významný (nízký řád) bit, takže ve výše uvedené grafice vidíte bity přicházející v pořadí: 01100010.

Doba „nečinnosti“ mezi bajty se přenáší jako spojité bity „1“ (přenosová linka je ve skutečnosti udržována trvale vysoko).

Chcete-li označit začátek bajtu, počáteční bit je vždy indikováno tahem za linku, jak je znázorněno na obrázku. Jakmile přijímač uvidí počáteční bit, čeká 1,5násobek času vzorkování a poté vzorkuje datové bity. Čeká 1,5krát, takže:

  • Přeskočí počáteční bit
  • Ukázky v polovině dalšího bitu

Pokud přenosová rychlost je například 9600 baudů, pak bude vzorkovací frekvence 1/9600 = 0,00010416 sekund (104,16 µs).

Tedy při 9600 baudech po obdržení spuštění bit přijímač čeká 156,25 µs a poté každých 104,16 µs vzorky.

Start bit timing

Účelem Stop Bit je zajistit, aby mezi každým bajtem byl určitě 1 bit. Bez stop bitu, pokud by bajt skončil nulou, pak by bylo nemožné, aby hardware rozpoznal rozdíl mezi tímto a počátečním bitem dalšího bajtu.

Produkovat výše uvedený výstup na Ne, můžete napsat tento kód:

  void setup () {Serial.begin (9600); Serial.print ("F"); } void loop () {}  

Počet datových bitů

Abyste ušetřili čas přenosu (za starých časů, heh), bylo vám povoleno zadat různé počty datových bitů. Hardware AtMega podporuje číslování datových bitů od 5 do 9. Je zřejmé, že čím méně datových bitů, tím méně informací můžete odeslat, ale čím rychleji to bude.


Paritní bity

Volitelně můžete mít paritní bit. To se vypočítá, je-li to požadováno, spočítáním počtu 1 ve znaku a následným zajištěním, že toto číslo je liché nebo sudé, nastavením paritního bitu na 0 nebo 1 podle potřeby.

Například pro písmeno „F“ (nebo 0x46 nebo 0b01000110) vidíte, že tam jsou 3 (v 01000110). Takže už máme lichou paritu. Paritní bit by tedy vypadal takto:

  • Žádná parita: vynechána
  • Sudá parita: a 1 (3 + 1 je sudé)
  • Zvláštní parita: a 0 (3 + 0 je liché)

Paritní bit, pokud je přítomen, se objeví za posledním datovým bitem, ale před stop bitem.

Pokud přijímač nezíská správný paritní bit, který se nazývá „chyba parity“. Znamená to, že existuje nějaký problém. Je možné, že odesílatel a přijímač jsou nakonfigurováni tak, aby používali různé přenosové rychlosti (bitové rychlosti), nebo na lince byl šum, který změnil nulu na jednu nebo naopak.

Některé starší systémy také používaly „značku“ parita (kde paritní bit byl vždy 1 bez ohledu na data) nebo „prostorová“ parita (kde paritní bit byl vždy 0 bez ohledu na data).


9bitový přenos

Některá komunikační zařízení používají 9bitová data, takže v těchto případech se paritní bit změní na 9. bit. K odeslání tohoto 9. bitu existují speciální techniky (registry jsou 8bitové registry, takže 9. bit musí být umístěn někde jinde).


Počet stop bitů

Počáteční vybavení mělo tendenci být elektronicky o něco pomalejší, takže aby měl přijímač čas na zpracování příchozího bytu, bylo někdy uvedeno, že odesílatel pošle dva stop bity. To v zásadě přidává více času tam, kde je datová linka držena vysoko (ještě jeden bitový čas), než se může objevit další počáteční bit. Tento extra bitový čas dává přijímači čas na zpracování posledního příchozího bajtu.

Pokud přijímač nezíská logickou 1, když má být zastavovací bit, nazývá se to „chyba rámce“. Znamená to, že existuje nějaký problém. Je docela pravděpodobné, že odesílatel a přijímač jsou nakonfigurováni tak, aby používali různé přenosové (bitové) rychlosti.


Notace

Sériová komunikace je obvykle indikována sdělením rychlosti, počtu dat bity, typ parity a počet stop bitů, například:

  9600/8-N-1  

Toto nám říká:

  • 9600 bitů za sekundu
  • 8 datových bitů
  • žádná parita (místo toho se může zobrazit: E = sudý , O = odd)
  • 1 stop bit

Je důležité, aby se odesílatel a příjemce shodli na výše uvedeném, jinak je nepravděpodobné, že by komunikace proběhla úspěšně.


Pin-outy

Arduino Uno má k dispozici digitální piny 0 a 1 pro hardwarový seriál:

Arduino Uno serial pins

Chcete-li připojit dvě Arduina, můžete vyměnit Tx a Rx takto:

Connecting two Arduinos together


Rychlost

Je podporována široká škála rychlostí (viz obrázek níže). „Standardní“ rychlosti jsou obvykle násobkem 300 baudů (např. 300/600/1200/2400 atd.).

S jinými „nestandardními“ rychlostmi lze manipulovat nastavením příslušných registrů. Třída HardwareSerial to dělá za vás. např.

  Serial.begin (115200); // nastavit rychlost na 115200 baudů  

Jako pravidlo platí, za předpokladu, že používáte 8bitová data, můžete odhadnout počet bajtů, které můžete vyslat za sekundu, dělením přenosová rychlost o 10 (z důvodu počátečního a koncového bitu).

Při 9600 baudech tedy můžete přenášet 960 bajtů ( 9600/10 = 960 ) za sekundu.


Chyby přenosové rychlosti

Přenosová rychlost na Atmega je generována dělením systémových hodin a počítáním do předem nastaveného čísla. Tato tabulka z datového listu ukazuje hodnoty registru a procenta chyb pro hodiny 16 MHz (například hodiny na Arduino Uno).

Baud rate errors

Bit U2Xn ovlivňuje dělitel frekvence hodin (0 = dělení 16, 1 = dělení 8). Registr UBRRn obsahuje počet, který procesor počítá.

Takže z výše uvedené tabulky vidíme, že z hodin 16 MHz získáme 9600 baudů takto:

  16000000/16/104 = 9615  

Vydělíme 104 a ne 103, protože počítadlo je nulové. Chyba zde tedy je 15/9600 = 0,0016 , což se blíží tomu, co říká výše uvedená tabulka (0,02%).

Zjistíte, že některé přenosové rychlosti mají vyšší míru chyb než ostatní.

Podle datového listu je maximální procento chyb u 8 datových bitů v rozmezí 1,5% až 2,0% (další podrobnosti viz datový list).


Arduino Leonardo

Arduino Leonardo a Micro mají odlišný přístup k sériové komunikaci, protože se připojují přímo přes USB k hostitelskému počítači, nikoli přes sériový port.

Z tohoto důvodu , musíte počkat, až bude Serial připraven (software vytvoří připojení USB), s několika dalšími řádky, jako je tento:

  void setup () {Serial.begin (115200); while (! Serial) {} // čekat, až budou připraveny sériové komunikace
Serial.print ("Fab"); } void loop () {}  

Pokud však chcete skutečně komunikovat pomocí pinů D0 a D1 (spíše než pomocí kabelu USB), musíte použít spíše Serial1 než Serial. Uděláte to takto:

  void setup () {Serial1.begin (115200); Serial1.print ("Fab"); } void loop () {}  

Úrovně napětí

Upozorňujeme, že Arduino používá pro sériovou komunikaci úrovně TTL. To znamená, že očekává:

  • „Nulový“ bit je 0V
  • „Jeden“ bit je + 5V

Starší sériové zařízení určené k připojení k sériovému portu počítače pravděpodobně používá úrovně napětí RS232, jmenovitě:

  • „Nulový“ bit je +3 až +15 voltů
  • A „bit má -3 až -15 voltů

Je to nejen„ obrácené “vzhledem k úrovním TTL („ jedna “je zápornější než„ nula “), Arduino nemůže zvládněte záporné napětí na jeho vstupních pinech (ani kladné napětí větší než 5V).

Proto potřebujete obvod rozhraní pro komunikaci s takovými zařízeními. Pouze pro vstup (do Arduina) to udělá jednoduchý tranzistor, dioda a několik rezistorů:

Inverting buffer

Pro dva Dálková komunikace musí být schopna generovat záporná napětí, takže je vyžadován složitější obvod. Například čip MAX232 to udělá ve spojení se čtyřmi kondenzátory 1 µF, které fungují jako obvody nabíjecího čerpadla.


Software Serial

Existuje knihovna s názvem SoftwareSerial, která umožňuje sériovou komunikaci (až do bodu) spíše v softwaru než v hardwaru. To má tu výhodu, že pro sériovou komunikaci můžete použít různé konfigurace pinů. Nevýhodou je, že sériové zpracování v softwaru je náročnější na procesor a náchylnější k chybám. Další podrobnosti najdete v části Seriál softwaru.


Mega2560

Arduino „Mega“ má 3 další hardwarové sériové porty. Na desce jsou označeny jako Tx1 / Rx1, Tx2 / Rx2, Tx3 / Rx3. Pokud je to možné, měly by být používány přednostně před SoftwareSerial. Chcete-li otevřít tyto další porty, použijte názvy Serial1, Serial2, Serial3, například takto:

  Serial1.begin (115200); // spustit hardwarový sériový port Tx1 / Rx1Serial2.begin (115200); // spustit hardwarový sériový port Tx2 / Rx2Serial3.begin (115200); // spustit hardwarový sériový port Tx3 / Rx3  

Přerušení

Odesílání i příjem pomocí knihovny HardwareSerial používají přerušení.

Odesílání

Když provedete Serial.print , data, která se pokoušíte vytisknout, se umístí do interní „přenosové“ vyrovnávací paměti. Pokud máte 1024 bajtů nebo více RAM (například na Uno), získáte 64bajtovou vyrovnávací paměť, jinak získáte 16bajtovou vyrovnávací paměť. Pokud má vyrovnávací paměť místo, vrátí se okamžitě Serial.print , takže váš kód nebude zdržován. Pokud zde není žádný prostor, pak „blokuje“ čekání na dostatečné vyprázdnění vyrovnávací paměti, aby tam bylo místo.

Poté, když hardware přenáší každý bajt, se volá přerušení („USART „Data Register Empty“ přerušení) a rutina přerušení odešle další bajt z vyrovnávací paměti ze sériového portu.

Příjem

Při příjmu dat se volá rutina přerušení ( přerušení „USART Rx Complete“) a příchozí bajt se umístí do „přijímací“ vyrovnávací paměti (stejné velikosti jako výše uvedená vysílací vyrovnávací paměť).

Když zavoláte Serial.available kód> zjistíte, kolik bytů je k dispozici v této „přijímací“ vyrovnávací paměti. Když zavoláte Serial.read , je bajt odstraněn z přijímací vyrovnávací paměti a vrácen do vašeho kódu.

Na Arduinos s 1 000 bajty RAM nebo více není žádný spěch k odstranění data z přijímací vyrovnávací paměti, pokud je nenecháte zaplnit. Pokud se zaplní, budou další příchozí data zahozena.

Všimněte si, že kvůli velikosti této vyrovnávací paměti nemá smysl čekat, až dorazí velmi velký počet bajtů, například:

  while (Serial.available () < 200) {} // čekat na doručení 200 bajtů  

To nikdy nebude fungovat, protože vyrovnávací paměť toho tolik neudrží.


Tipy

  • Před čtením se vždy ujistěte, že jsou k dispozici data. Například je to špatné:

      if (Serial.available ()) {char a = Serial.read (); char b = Serial.read (); // nemusí být k dispozici}  

    Test Serial.available zajišťuje pouze to, že máte k dispozici jeden bajt, ale kód se pokusí přečíst dva. Může to fungovat, pokud jsou ve vyrovnávací paměti dva bajty, pokud ne, dostanete -1 vrácenou, která bude po vytištění vypadat jako „ÿ“.

  • Uvědomte si, jak dlouho trvá odeslání dat. Jak již bylo zmíněno výše, při 9600 baudech přenášíte pouze 960 bajtů za sekundu, takže pokus o odeslání 1000 čtení z analogového portu při 9600 baudech nebude příliš úspěšný.


Reference

Na 1. grafice: se šipkami to vypadá, že se jako první vysílá stop bit. Pokud jste si vyměnili Rx / Tx a směr šipek, myslel bych si, že je to méně matoucí.
Mělo se číst zleva doprava (stejně jako tato věta), a tak se věci nalevo odehrávají jako první. Dej to takto: na osciloskopu bys tak viděl stopu.
Dobře, s vysvětlením osciloskopu to kupuji. :-)
Myslel jsem si však, že váš názor má velký smysl. Co si myslí ostatní? Bylo by jasnější, kdyby se šipky obrátily a já si vyměnil Rx / Tx?
Myslím, že počínaje koncem Tx (levá strana), pokud sledujete dráhu pulzů (ve směru šipek), nejprve zasáhnou notaci „Start bit“ a poté datové bity a poté „ Stop bit ".
Ahoj Nicku! Skvělý příspěvek. Nevím, proč mě tvé použití slova „odpadky“ v prvním odstavci obtěžuje. Vím, že jsem tento termín (a další jako „gobledygoop“) použil sám. Jelikož se jedná o referenční článek, myslím, že existuje lepší, technický termín, který by mohl být použit.
Není to slovo, které používám tak často („odpadky“ jsou obvyklejší tam, kde jsem) - předpokládám, že jsem myslel na „smetí dovnitř, smetí ven“ - ne že by to v tomto případě platilo). Myslím, že „gobledygoop“ může být matoucí pro lidi, kteří nemají angličtinu jako první jazyk. Pokusím se vymyslet lepší způsob, jak to vyjádřit. :)
@linhartr22 Upravil jsem to tak, aby četlo „nesmyslná data“, která jsou pravděpodobně blíže.
@NickGammon: Skvělý příspěvek. Mohl byste mi říct, proč sériový monitor Arduino IDE (1.8.9) nemá problémy s komunikací s mým Arduino Micro, i když jsou dva nakonfigurovány pro divoce odlišné přenosové rychlosti, např. 300 b / s, respektive 115 200 b / s? Předpokládám, že to má co do činění s přímým připojením USB, ale má tedy nastavení přenosové rychlosti pro Micro vůbec nějaký význam?
Zdá se, že to naznačuje, že na tom nezáleží: https://arduino.stackexchange.com/a/31034 (pokud nenastavím 1200 bps, pak ukončete sériový monitor, protože to podle očekávání spustí reset)
Ano, viz [Začínáme s Arduino ... Micro] (https://www.arduino.cc/cs/Guide/ArduinoLeonardoMicro) * U modelů Leonardo, Leonardo ETH a Micro odkazuje hlavní třída Serial na virtuální seriál ovladač na desce pro připojení k počítači přes USB. Není připojen k fyzickým pinům 0 a 1, jako je tomu na Uno a starších deskách. Chcete-li použít hardwarový sériový port (piny 0 a 1, RX a TX), použijte Serial1 *. * Skutečný * sériový port je Serial1, port USB se nazývá Serial. Pomocí Serial na Micro můžete nastavit přenosovou rychlost na 1 a stále získat velmi rychlý sériový tisk.


Tyto otázky a odpovědi byly automaticky přeloženy z anglického jazyka.Původní obsah je k dispozici na webu stackexchange, za který děkujeme za licenci cc by-sa 3.0, pod kterou je distribuován.
Loading...