Vaša IP adresa: 3.144.86.138
Počet návštev: 30523

Lekcia 3: USART

Sériová komunikácia patrí medzi najrozšírenejšie spôsoby prenosu. Jednotlivé prvky sú v časovej postupnosti vysielané po jednej prenosovej linke. Pri príjme dát je potrebné, aby bol prijímač synchronizovaný s vysielačom. Prijímač teda musí poznať začiatok a koniec, kedy dochádza k zmene signálového stavu - začiatky a konce blokov dát, takzvaný dátový rámec. Na základe týchto údajov prijímač stanoví rozhodujúci okamih pre vyhodnotenie dátového rámca.

Synchrónne/asynchrónne sériové rozhranie USART (Universal Synchronous/Asynchronous Receiver and Transmitter) je časť hardvéru pre sériovú komunikáciu v asynchrónnom režime (RS-232, RS-422, ...) alebo synchrónnom režime (SPI). Asynchrónny režim býva označovaný ako UART (Universal asynchronous receiver/transmitter). USART vysiela údaje na pine označovanom ako TX alebo TXD (transmit) a prijíma na pine RX alebo RXD (receive). Kľudová úroveň signálu je log. 1 ( pokiaľ neprebieha vysielanie ani príjem). Vysielanie začína zmenou hodnoty signálu na log. 0 po dobu jedného bitu (tzv. start-bit). Následne sa posiela najnižší dátový bit (LSB), posledný najvýznamnejší dátový bit (MSB), ktorý je nasledovaný jedným alebo dvomi stop bitmi, ktoré majú opäť úroveň log. 1. Po odvysielaní posledného stop-bitu môže začať prenos ďalšieho bajtu. Počet dátových bitov môže byť od 5 do 9. Deviaty dátový bit môže mať funkciu paritného bitu.

Formát dátového rámca. St - Start bit (vždy nízka úroveň); (0 - 8) - dátové bity; P - paritný bit; Sp - Stop bit (vždy vysoká úroveň); IDLE - bez prenosu dát. Bity uvedené v [ ] nie sú povinné a dátový rámec ich nemusí obsahovať.

Dôležité registre

V tejto časti sú opísané niektoré registre súvisiace s rozhraním USART, ktoré sú využité v príkladoch nižšie. V názve registrov je index n. Index n je použitý preto, lebo niektoré MCU z rodiny AVR majú k dispozícii viacero rozhraní USART (napr. ATmega328PB má 2 rozhrania USART [USART0, USART1], ATmega2560 má 4 rozhrania USART [USART0 - USART3]). MCU ATmega328P má iba jedno rozhranie USART, preto v názvoch registrov treba za index n dosadiť číslo 0 (napr. UDR0, UCSR0A, ...).


UDR0 - Vysielací a prijímací register (8-bit). Zápisom bajtu do registra UDR0 vykonáme odoslanie bajtu cez USART. Čítaním registra UDR0 získame prijatý bajt cez rozhranie USART. V prípade opakovaného prijímania dát musí byť vyčítavanie registra UDR0 dostatočne rýchle, aby nedochádzalo k prepisovaniu registra bez toho, aby sa prijatý bajt spracoval.


UCSR0A - Register slúžiaci na kontrolu prijatia/odoslania bajtu a na nastavenie dvojnásobnej rýchlosti prenosu.

  • Na kontrolu prijatia bajtu súži bit RXC0. Bit RXC0 je nastavený na log.1, keď sa v prijímacom registri nachádza neprečítaný bajt a je vynulovaný, keď je prijímací buffer prázdny (napr. neobsahuje neprečítané dáta).
  • Bit TXC0 je nastavený na log.1, keď je odoslaný celý dátový rámec (všetky bity) a vo vysielacom registri (bufferi) nie sú žiadne nové dáta. Bit TXC0 je nulovaný automaticky, keď sa vyvolá prerušenie kompletného prenosu (transmit complete interrupt) alebo manuálne zápisom log.1 na poradie bitu TXC0.
  • Bit UDRE0 signalizuje pripravenosť registra UDR0 na prijatie nových dát. Ak je bit UDRE0=1, tak je buffer UDR0 prázdny a môžu byť do neho zapísané nové dáta.
  • Bit U2X0 slúži na nastavenie dvojnásobnej rýchlosti prenosu. Ak je bit U2X0 nastavený na log.1, tak je predelička udávajúca rýchlosť prenosu (Braud Rate) zmenená z hodnoty 16 na hodnotu 8 a tak je rýchlosť prenosu dvojnásobná. Toto nastavenie funguje iba v asynchrónnom móde.

UCSR0B - Register slúžiaci na zapnutie/vypnutie prijímača a vysielača a ďalej na zapnutie prerušení pri prijíme a vyslaní dát.

  • Ak je bit RXCIE0=1, tak je zapnuté prerušenie pri príznaku (flag) RXC0, t.j. pri prijatí bajtu cez USART. Aby bolo uvedené prerušenie funkčné, tak musia byť zapnuté globálne prerušenia sei().
  • Ak je bit TXCIE0=1, tak je zapnuté prerušenie pri príznaku (flag) TXC0, t.j. pri odoslaní bajtu cez USART. Aby bolo uvedené prerušenie funkčné, tak musia byť zapnuté globálne prerušenia sei().
  • Ak je bit RXEN0=1, tak je zapnutý prijímač (prijímanie dát cez USART). Zapnutím prijímača sa prepíše normálna funkcia portu na pine RXD (PD0).
  • Ak je bit TXEN0=1, tak je zapnutý vysielač (vysielanie dát cez USART). Zapnutím vysielača sa prepíše normálna funkcia portu na pine TXD (PD1).

UCSR0C - Register slúžiaci na nastavenie módu (synchrónny/asynchrónny), parity, počtu stop bitov a počtu dátových bitov USART komunikácie.

  • Bity UMSEL01 a UMSEL00 slúžia na nastavenie synchrónneho alebo asynchrónneho módu.
  • Bity UPM01 a UPM00 slúžia na nastavenie parity.
  • Bit USBS0 slúži na nastavenie počtu stop bitov.
  • Bity UCSZ02, UCSZ01 a UCSZ00 slúžia na nastavenie počtu dátových bitov. Bit UCSZ02 sa nachádza v registri UCSR0B.

Prenosovú rýchlosť (Baud Rate) môžeme nastaviť zápisom adekvátnej hodnoty do 12-bitového registra UBRR0.

Nasledujúca tabuľka uvádza vzorce na výpočet hodnoty registra UBRR0 podľa želanej rýchlosti prenosu BAUD.

Tab. 1: Výpočet hodnoty registra UBRR0 podľa požadovanej prenosovej rýchlosti (Baud Rate). Tab. 1: Výpočet hodnoty registra UBRR0 podľa požadovanej prenosovej rýchlosti (Baud Rate).

Prenosové rýchlosti cez sériovú linku sú štandardizované, preto je v datasheete pre ATmega328P uvedená tabuľka, ktorá udáva hodnotu registra UBRR0 pre zvolenú rýchlosť prenosu (Baud Rate) a danú frekvenciu MCU (fOSC). V závislosti od frekvencie MCU (fOSC) a s použitím vzorcov v Tab. 1 nie je možné nastaviť ľubovoľný Baud Rate, ktorý je uvedený v Tab. 2 a Tab. 3. V tabuľke sa uvádza stĺpec Error, ktorý udáva percentuálnu chybu nastavenej (vypočítanej) rýchlosti prenosu (Baud Rate) od požadovanej. Z tabuľky je vidieť, že pre fOSC=8 MHz je možné s chybou 0.0% nastaviť iba zopár prenosových rýchlostí. Na dosiahnutie spoľahlivého prenosu by mala byť chyba prenosu menšia ako 0.5%. To znamená, že aj pri použití fOSC=8 MHz môžeme využiť nastavenia, pri ktorých je v Tab. 2 uvedená chyba prenosu 0.2%. Iná frekvencia MCU (napr. fOSC=11.0592 MHz) umožňuje výber z viacerých prenosových rýchlostí s chybou 0.0%.

Tab. 2: Nastavenie prenosovej rýchlosti na základe frekvencie MCU (8 MHz - 14.7458 MHz). Tab. 2: Nastavenie prenosovej rýchlosti na základe frekvencie MCU (8 MHz - 14.7458 MHz). Tab. 3: Nastavenie prenosovej rýchlosti na základe frekvencie MCU (16 MHz - 20 MHz). Tab. 3: Nastavenie prenosovej rýchlosti na základe frekvencie MCU (16 MHz - 20 MHz).

Komunikácia USART prebieha medzi minimálne dvomi zariadeniami. Najčastejšie sa používa na komunikáciu medzi zariadením (MCU) a počítačom alebo na komunikáciu medzi MCU a periférnymi obvodmi. Na overenie správnosti naprogramovanej komunikácie cez USART využijeme PC. Nové počítače už neobsahujú 9-pinový konektor pre sériovú komunikáciu s rozhraním RS232 (štandard využívajúci rozhranie USART). Toto rozhranie je nahradené rozhraním USB. Z tohto dôvodu je potrebné medzi MCU a PC vložiť konvertor rozhraní USB/USART, napr. FT232RL, ktorý je využitý v Mega Development Board. Na testovanie príkladov, ktoré sú uvedené nižšie, bola vytvorená aplikácia pre PC, ktorú si môžete stiahnuť tu.

Aplikácia USART. Ukážka aplikácie USART s popisom ovládacích tlačidiel.

Príklad č. 1

V nasledujúcom príklade je inicializované rozhranie USART s nasledujúcimi parametrami:

  • asynchrónny mód
  • 8 dátových bitov
  • 1 stop bit
  • žiadny paritný bit
  • rýchlosť prenosu 19 200 Baud

Pomocou rozhrania USART je do počítača zaslaný reťazec s menom po stlačení tlačidla S0, ktoré je pripojené k pinu PINB0. Funkčnosť kódu si môžete overiť pomocou aplikácie, ktorá bola uvedená vyššie.

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
/***** ***** ***** ***** ***** *****
* Nasledujuca cast kodu je nadbytocna, pretoze danemu nastaveniu seriovej
* komunikacie vyhovuje prednastavena (default) hodnota registrov
***** ***** ***** ***** ***** *****/
UCSR0C&=~(1<<USBS0); //nastavenie jedneho stop bitu
UCSR0C&=~((1<<UPM01)|(1<<UPM00)); //nastavenie ziadnej parity
UCSR0C|=(1<<UCSZ01)|(1<<UCSZ00); //nastavenie 8 datovych bitov
UCSR0B&=~(1<<UCSZ02); //nastavenie 8 datovych bitov
/* Koniec nadbytocnej casti kodu
***** ***** ***** ***** ***** *****/

UBRR0=25; //nastavena rychlost 19200 Baud (z datasheetu) pri f_MCU=8MHz

UCSR0B|=(1<<TXEN0); //zapnutie vysielaca

DDRD=0; //PORTD ako vstup
PORTD=255; //pull-up na PORTD

char meno[15]="Ferko Mrkvicka"; //+1 znak navyse kvoli koncu retazca \0
while (1)
{
if (! (PIND&(1<<PIND0))) //ci bolo stlacene tlacidlo pripojene k pinu PIND0
{
for (unsigned char k=0;k<15;k++) //odosielanie retazca po jednotlivych znakoch
{
while ((UCSR0A&(1<<UDRE0))==0) ; //kontrola vyprazdnenia buffera UDR0
UDR0=meno[k]; //odoslanie znaku
}
//cakanie 1 s (10 x 100ms),aby nedoslo k
//viacnasobnej registracii stlacenia tlacidla
for (uint8_t k=0;k<10;k++)
_delay_ms(100);
}
}
}

Prijatie reťazca v aplikácii USART Zaslaný reťazec v aplikácii USART (nutné zaškrtnúť políčko Wait for string).

Príklad č. 2

Nasledujúci príklad plní rovnakú funkciu ako príklad č. 1 s tým rozdielom, že inicializácia USART a odosielanie znaku cez USART sú vykonané vo funkciách. Zatriedenie jednotlivých funkčných blokov kódu do funkcií výrazným spôsobom uľahčuje čitateľnosť kódu a tým ho sprehľadňuje.

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

void USART_Init()
{
// Nastavenie USART-8 datovych bitov,jeden stop bit,ziadna parita
// - uvedene parametre su vychodiskove hodnoty registrov,
// preto nie je potrebne nastavovat
UBRR0=25; //nastavena rychlost 19200 Baud (z datasheetu) pri f_MCU=8MHz
UCSR0B|=(1<<TXEN0); //zapnutie vysielaca
}

void USART_send(unsigned char bajt)
{
while ( !( UCSR0A & (1<<UDRE0)) ) ; //pocka na vyprazdnenie buffera
UDR0 = bajt; //odoslanie bajtu cez USART
}

int main(void)
{
USART_Init(); //inicializacia USART

DDRD=0; //PORTD ako vstup
PORTD=255; //pull-up na PORTD

char meno[15]="Ferko Mrkvicka"; //+1 znak navyse kvoli koncu retazca \0
while (1)
{
if (! (PIND&(1<<PIND0))) //ci bolo stlacene tlacidlo pripojene k pinu PIND0
{
for (unsigned char k=0;k<15;k++) //odosielanie retazca po jednotlivych znakoch
{
USART_send(meno[k]);
}
//cakanie 1 s (10 x 100ms),aby nedoslo k
//viacnasobnej registracii stlacenia tlacidla
for (uint8_t k=0;k<10;k++)
_delay_ms(100);
}
}
}

Príklad č. 3

Tento príklad slúži na odosielanie signálu tvaru píly do MCU. Píla obsahuje hodnoty od 0 do 255 a jednotlivé hodnoty sa odosielajú s frekvenciou 250 Hz, t.j. hodnoty sú odosielané každé 4 ms (1/250). MCU monitoruje stav linky RTS, ktorú ju možné zmeniť v PC. Ak je stav linky RTS = log.0, tak dochádza k odosielaniu jednotlivých hodnôt píly. Naopak, keď je stav linky RTS = log.1, tak nedochádza k posielaniu hodnôt.

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

void USART_Init()
{
// Nastavenie USART-8 datovych bitov,jeden stop bit,ziadna parita
// - uvedene parametre su vychodiskove hodnoty registrov,
// preto nie je potrebne nastavovat
UBRR0=25; //nastavena rychlost 19200 Baud (z datasheetu) pri f_MCU=8MHz
UCSR0B|=(1<<TXEN0); //zapnutie vysielaca
}

void USART_send(unsigned char bajt)
{
while ( !( UCSR0A & (1<<UDRE0)) ) ; //pocka na vyprazdnenie buffera
UDR0 = bajt; //odoslanie bajtu cez USART
}

int main(void)
{
USART_Init(); //inicializacia USART

DDRD=0; //PORTD ako vstup
PORTD=255; //pull-up na PORTD
PORTD&=~(1<<PIND2); //vypnutie pull-up na PIND2 (RTS)
uint8_t cislo=0;
while (1)
{
if (! (PIND&(1<<PIND2))) //ci je stav linky RTS = log.0
{
USART_send(cislo);
cislo++; //inkrementacia hodnoty premennej cislo
_delay_ms(4); //odosielanie s frekvenciou 250 Hz (1/4ms = 250 Hz)
}
}
}

Zobrazenie píly v aplikácii USART Prijatý signál v tvare píly v aplikácii USART.

 Na stiahnutie

Aplikácia USART