Uživatel:Langsmar

Z MAM wiki

Přejít na: navigace, hledání

Práca vypracovaná spolu s A. Ostaninom. Na ukážkových programoch sme pracovali spoločne.

Obsah

[editovat] Komunikácia AVR s PC

V tejto práci by som rád opísal komunikáciu mikrokontroléra AVR s PC pomocou asynchronného sérioveho kanála (v angličtine označenie UART - Universal Asynchronous Receiver Transmiter). Väčšina mikrokontrolérov AVR má perifériu sérioveho kanálu implementovanú. V katalógovom liste sa popis sérioveho kanálu vyskytuje pod označením USART. Táto verzia umožňuje okrem klasického asynchronného režimu aj režim synchrónny.

Príklady k tejto práci boli otestované na mikrokontroléri ATmega16, preto aj popis registrov bude tomu prispôsobený. Na iných verziách AVR-iek by to malo byť obdobné, poprípade s malými úpravami (Ak napríklad nejaký iný mikrokontrolér obsahuje viac sériových kanálov, treba určiť ktorý použijeme, problémy môžu byť aj s adresami prerušení).

[editovat] Sériový kanál v mikrokontroléroch AVR

Mikrokontrolér ATmega16 obsahuje jeden plne duplexný sériový kanál, ktorý dokáže pracovať v synchrónnom i asynchrónnom režime. Širšie využívaný je asynchrónny režim, ktorému sa budem ďalej venovať.

[editovat] Registre

Sériový kanál sa z programu ovláda pomocou registrov UCSRA, UCSRB, UCSRC, UBRRL,UBRRH, UDR. Je uvedený len stručný popis, plný popis je uvedený v datasheete.

  • UCSRA (USART Control and Status Register A)
    • Bit 7 - RXC (Receive Complete) - bit je nastavený do 1, ak sú ešte neprečítané dáta v príjimacom bufferi. Tento bit môže byť zdrojom prerušenia pri príjme dát
    • Bit 6 - TXC (Transmit Complete) - bit je nastavený do 1, ak sa odoslali všetky dáta z vysielacieho buffera. Môže byť zdrojom prerušenia pri odoslaní dát
    • Bit 5 - UDRE (USAR Data Register Empty) - ak je 1, príjimací buffer je prázdny, možno príjimať ďalšie dáta
    • Bit 4 - FE (Frame Error) - ak je 1, vyskytla sa chyba v priatom rámci
    • Bit 3 - DOR (Data OverRun) - ak je príjimací buffer plný a detekuje sa ďalší štartbit, nastaví sa do 1
    • Bit 2 - PE (Parity Error) - ak sa vyskytla chyba parity, nastaví sa do 1
    • Bit 1 - U2X - bit sa používa pri výpočte prenosovej rýchlosti v asynchronnom režime
    • Bit 0 - MPCM (Multi-Processor Communication Mode) - zapísaním hodnoty 1 možno aktivovať viacprocesorovú komunikáciu.
Soubor:UCSRA.PNG


  • UCSRB (USART Control and Status Register B)
    • Bit 7 - RXCIE (RX Complete Interrupt Enable) - zapísaním hodnoty 1 sa aktivuje prerušenie pri príjme
    • Bit 6 - TXCIE (TX Complete Interrupt Enable) - zapísaním hodnoty 1 sa aktivuje prerušenie pri vysielaní
    • Bit 5 - UDRIE (USAR Data Register Empty Interrupt Enable) - zapísaním hodnoty 1 sa aktivuje prerušenie ak dátový register prázdny
    • Bit 4 - RXEN (Receiver Enable) - zapísaním hodnoty 1, sa aktivuje činnosť príjimača USART
    • Bit 3 - TXEN (Transmit Enable) - zapísaním hodnoty 1, sa aktivuje činnosť vysielača USART
    • Bit 2 - UCSZ2 (Character Size) - v kombinácií s UCSZ0 a UCSZ1 nastavuje počet dátových bitov v rámci
    • Bit 1 - RXB8 (Receive Data Bit 8) - bit číslo 8 (resp. 9. bit ak sa cisluje od 1), pri prijme 9 dátových bitov v rámci
    • Bit 0 - TXB8 (Transmit Data Bit 8) - bit číslo 8 pri vysielaní 9 dátových bitov v rámci
Soubor:UCSRB.PNG


  • UCSRC (USART Control and Status Register C)
    • Bit 7 - URSEL (Register Select) - bit vyberá medzi prístupom do UCSRC alebo do UBRRH. Tieto registre majú rovnakú adresu
    • Bit 6 - UMSEL (Mode Select) - nastavenie synchrónneho alebo asynchrónneho režimu
    • Bit 5 - UPM1 (Parity mode 1) - spolu s UPM0 sa nastavuje parita
    • Bit 4 - UPM0 (Parity mode 0)
    • Bit 3 - USBS (Stop Bit Select) - nastavenie formátu stopbitu
    • Bit 2 - UCSZ1 (Character size) - v kominácií s UCSZ0 a UCSZ2 nastavuje počet dátových bitov v rámci. Viď tabuľka 1
    • Bit 1 - UCSZ0 (Character size)
    • Bit 0 - UCPOL (Clock Polarity) - Nastavenie polarity hodinového signálu. Má význam len v synchrónnom režime
Soubor:UCSRC.PNG

Nastavenie počtu dátových bitov v rámci (tabuľka 1):

Soubor:data_bits.PNG


  • UBRRL, UBBRH (USART Baud Rate Register Low/High)
Soubor:UBRR.PNG

Spoločne sa tento register nazýva UBRR. Horný bajt je UBRRH, dolný bajt je UBRRL. Register UBBRH je 4 bitový, a prekrýva sa s UCSRC. Dohromady môže dvojica UBBRL, UBBRH uchovať 12 bitové číslo. Toto číslo určuje prenosovú rýchlosť. Výpočet prenosovej rýchlosti je uvedený nižšie.


  • UDR (USART I/O Data Register)
Soubor:UDR.PNG

Tento 8 bitový register v skutočnosti tvoria dva registre, ktoré majú spoločnú adresu. Jeden je príjimací, druhý vysielaci. Pre čítanie a zápis tak programátor pristupuje len k 1 registru. Čo treba odoslať sériovým kanálom sa zapíše do tohto registra. Naopak, všetko čo sa príjme je uložené v tomto registri.


[editovat] Nastavenie prenosovej rýchlosti

Rýchlosť prenosu sa určuje hodnotou, ktorá sa zapíše do registrov UBRRL, UBRRH. Táto hodnota je závislá od použitej taktovacej frekvencie. Vypočítať ju možno podľa nasledujúcich vzťahov. V uvedených príkladoch nižšie budem využívať prenosovú rýchlosť 9600 Bd pri taktovacej frekvencií 1 MHz. Hodnota UBRR pri U2X = 1 bude 12 (UBRRH = 0, UBBRL = 12).

Soubor:baud_rate.PNG

Pre bežne používané prenosové rýchlosti a taktovacie frekvencie sú v datasheete tabuľky, kde možno príslušnú hodnotu UBRR ľahko vyčítať. Podľa tabuľky je hodnota UBRR pre 9600 Bd a takte 1 MHz taktiež 12. Treba ale nastaviť bit U2X v registri UCSRA. Pri tejto konfigurácií je chyba pri generovaní prenosovej rýchlost 0,2%. Ak by bolo U2X = 0, tak hodnota UBRR by bola 6, ale s chybou -7% od požadovanej prenosovej rýchlosti.

Soubor:baud_rate_table.PNG


[editovat] Inicializácia sériového kanála

V nasledujúcom príklade je ukázané nastavenie sériového kanála pomocou vyššie popísaných registrov. Zapne sa asynchronny režim, rámec bude mať 8 dátových bitov bez parity, 1 stop bit. Prenosová rýchlosť 9600 Bd je uvažovaná pri takte mikrokotroléra 1 MHz. Tomu odpovedá konštanta 12, ak je U2X = 1. Generovanie prerušenia je vypnuté. Fragment programu v assembleri je vytvorený ako podprogram, príklad v C ako funkcia.

[editovat] Assembler

init_UART:
    ldi R16,0b00000010       ; U2X = 1
    out UCSRA,R16
    ldi R16,0b00011000       ; vypnutie generovania prerusenia, zapnutie prijimaca a vysielaca
    out UCSRB,R16
    ldi R16,0b10000110       ; asynchronny rezim, ziadna parita, 1 stop bit, 8 datovych bitov v ramci
    out UCSRC,R16
    ldi R16,0
    out UBRRH,R16            ; nastavenie prenosovej rychlosti UBRR = 12 -> 9600 Bd pri 1 MHz taktovani
    ldi R16,12
    out UBRRL,R16
    ret

[editovat] C

void init_UART()
{
    UCSRA = _BV(U2X);  
    UCSRB = _BV(RXEN) | _BV(TXEN);
    UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
    UBRRH = 0;
    UBRRL = 12;
}

[editovat] Piny na puzdre

Asynchrónny sériový kanál s vonkajšim svetom komunikuje cez piny označené RXD a TXD. Pin RXD slúži na príjem, TXD slúži na vysielanie sériových dát. Pre zabezpečenie komunikácie treba okrem týchto pinov prepojiť aj zeme (GND) medzi komunikujúcimi stranami. Vysielané dáta z mikrokontroléra lezú von pinom TXD, ale na druhej strane kanálu vstupujú na pin RXD. Rovnako dáta ktoré mikrokontrolér príjima na pine RXD vystupujú na druhej strane kanála pinom TXD.

Soubor:atmega16_piny.PNG Soubor:uart_prepojenie.png

[editovat] Prepojenie AVR s PC

Mikrokontrolér a PC sa pri komunikácia musia vhodne spojiť. Ak má PC fyzický sériový port (RS-232), vývody TXD, RXD z AVR-ka nemožno priamo prepojiť s pinmi RXD a TXD na strane sériového portu na PC. Problém je v rozdielnych napäťových urovňach. Musí sa použiť vhodný prevodník logiky TTL na RS-232.

V prípade ak PC nemá fyzický sériový port, môže sa použiť prevodník RS-232/USB alebo TTL/USB. Na strane PC treba v takomo prípade nainštalovať ovládač, ktorý v systéme vytvára virtuálny sériový port. Aplikácie vidia klasický sériový port, ale fyzická komunikácia prebieha cez USB. Táto komunikácia je pre obe strany (AVR aj software na PC) transparentná. Programy na oboch stranach pracujú štandardne ako so sériovým kanálom.

[editovat] Cez RS-232

Ak má PC sériový port je výhodna táto možnosť. Napäťový prevodník možno zostaviť buď z diskrétnych súčiastok alebo možno použiť integrovaný obvod MAX232. Existuje viacej klonov tohto obvodu od rôznych výrobcov a ich parametre sa môžu líšíť napr. veľkosťou kondenzátorou, ktoré treba pripojiť. To sa da nájsť v katalógom liste pre konkrétny typ. Na prepojenie PC s možno použiť 3 žilový kábel. Bloková schéma tohto typu spojenia je na obrázku.

Soubor:kom_rs232.png

Na ďalšom obrázku je ilustratívne naznačené zapojenie prevodníka MAX232 a jeho puzdro.

Soubor:MAX232.gif Soubor:max232_1.gif


[editovat] Cez prevodnik RS-232/USB

Táto varianta je vhodná v prípade, ak už existuje hotové zariadenie, ktoré má len sériový port RS-232 ale PC ho nemá. Možno využiť prevodník RS-232/USB, ktorý možno kúpiť v skoro každom obchode s PC za pár korún. Pre väčšinu zariadení to stačí, niektoré zariadenia ale využívajú vlastnosti, ktoré má len fyzický sériový port a tento prevodník ich nemôže splniť.

Soubor:kom_cez_prevodnik.png

Sám využívam túto variantu na mojom staršom vývojovom kite, ktorý má vyvedený sériový kanál RS-232. V prípade ak ho potrebujem pripojiť k stolnému PC, není problém. Na notebooku, ktorý fyzický sériový port nemá, použijem tento prevodník. Funguje to bez problémov.


[editovat] Cez prevodník TTL/USB

V súčasnosti je toto veľmi populárna varianta. Celá komunikácia beží po zbernici USB, ale obe komunikujúce strany komunikujú ako keby boli spojené klasickým sériovým kanálom. Ten sa programovo ovláda omnoho jednoduchšie ako zložitejšie USB.

Soubor:kom_usb.png

Existuje viac druhov obvodov, ktoré túto variantu komunikácie vedia zabezpečiť. Celkom obľúbený obvod je FT232XX od firmy FTDI. Ten sa vyrába vo viacerých modifikáciach. Verzia FT232RL má takmer všetky funkcie integrované v čipe, k puzdru treba pripojiť len minimum obvodov. Obvod má mnoho nastavení, ktorý prípadny záujemca nájde podrobne popísané v datasheete. Taktiež na webe je mnoho praktickým zapojení s týmto obvodom. V krátkosti uvediem, že okrem dokáže bežať aj v inom móde ako prevodník klasického sériového kanála a dokáže napájať zariadenie priamo z USB. Na obrázku je schéma zapojenia vo verzií s externým napájanim.

Soubor:ft232rl.jpg Soubor:ft232rl_sch.PNG

[editovat] Iné varianty

Iná varianta komunikácie medzi mikrokontrolérom a PC je softwarová emulácia USB protokolu na AVR-ku. Táto varianta nevyužíva vstavaný sériový kanál, ktorý je popisovaný na tejto stránke. K puzdru AVR-ka stačí pripojiť len pár súčiastok okolo a konektor USB. Na internete existuje viacero projektov venujúcej sa tejto problematike, jedna zo stránok je napr. http://www.obdev.at/products/vusb/index.html. Sú tu dostupné knižnice funkcí pre prácu s USB, ktoré možno využiť vo vlastnom programe.

[editovat] Obsluha na PC

Na PC existuje viac spôsobov ako komunikovať po sériovej linke. Jedna z možností je použiť klasický terminál, druhá možnosť je napísať si vlastný program. Prvá možnosť je veľmi jednoduchá, vhodná na základnú obojsmernú komunikáciu. Ak sa majú prijate dáta aj nejako spracovať, nezostáva nič iné než si napísať vlastný program. Vlasný program je vhodný aj v prípade, ak má byť ovládanie zariadenia pripojeného k PC užívateľsky príjemne. Nie každý miluje terminál, príkazový riadok a pod :)

[editovat] Terminál

Na ladenie a základnú obojsmernú komunikáciu sa určite zíde terminál. Existuje množstvo variant, celkom podarená verziu pre Windows možno nájsť na tejto stránke

Soubor:terminal.png

Pri používaní sa nastaví sériový port (napr. COM3, ktorý bol vytvorený ovládačom prevodníka USB/RS-232), prenosová rýchlosť, počet dátových bitov, parita, stap bity. Nastavenia musia byť zhodné s nastaveniami na druhej strane linky. Po nastaveniach sa tlačidlom Connect otvorí sériový kanál. V oblasti označenej Receive možno vidieť, čo mikropokontrolér posiela, naopak do zápisom do oblasti Transmit možno niečo poslať mikrokotroléru. Ako vidno, program disponuje množstvom funkcií, ktoré pre terajšie účely niesu podstatné.

[editovat] Vlastný program

Napísať si vlastný program vyžaduje nejaké tie znalosti z programovania na PC. Návod na komunikáciu cez sériovú linku, ktorý možno využiť vo svojom programe možno nájsť napr. na tejto stránke. Sú tam uvedené fragmenty programu v jazyku C určené pre operačný systém Windows.

[editovat] Priklady

Všetky uvedené programy používajú rovnaké nastavenie sériového kanála - 9600 Bd, 8 dátových bitov, 1 stop bit, žiadny paritný bit. Sú napísané v jazyku C. Zoradené sú od jednoduchších po zložitejšie. Na strane PC bol na komunikáciu použitý popisovaný terminál. Screenshot terminálu je priložený ku každému príkladu.

[editovat] Prvý program

Prvý program demonštruje jednoduchú obojsmernú komunikáciu cez sériovy kanál. Nevyužíva prerušenia. Program neustále čaká na vstup. Ak je vstup znak x, tak pošle naspäť smajlíka :-). Na iné znaky program nereaguje.

#include <avr/io.h>

int main()
{
    /* prenosova rychlost 9600Bd pri takte 1MHz */
    UBRRH = 0;
    UBRRL = 12;

    /* zapnuty bit dvojnasobnej rychlosti */
    UCSRA = _BV(U2X);  
    /* zapnutie prijimaca a vysielaca */
    UCSRB = _BV(RXEN) | _BV(TXEN);
    /* datovy ramec ma 8 bitov, vsetky ostatne nastavenie su predvolene */
    UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
    
    /* nekonecna programova slucka */
    for (;;) 
    {

	/* cakanie pokym je vstupny buffer prazdny */
        while((UCSRA & _BV(RXC)) == 0);
        
        /* ak nieco prislo, skontroluje sa, ci je to znak x */
        if (UDR == 'x') 
        {

            /* ak prisiel znak x, posle sa naspat smajlik :-) 
	       posiela sa postupne po jednotlivych bitoch
	       po kazdom zapise do buffera UDR sa caka kym sa 
	       nevyprazdni, tj data sa neodoslu
	    */

             while((UCSRA & _BV(UDRE)) == 0);
             UDR = ':';
             while((UCSRA & _BV(UDRE)) == 0);
             UDR = '-';
             while((UCSRA & _BV(UDRE)) == 0);
             UDR = ')';
        }
    }

    return 0;
}

A ako to vyzerá v terminále.

Soubor:terminal_priklad1.png

[editovat] Prerušenia

Program demonštruje použitie prerušena pri príjme. Obsluha prerušenia pri vysielaní nič nerobí. Je uvedená len demonštratívne, ako vyzerá :) Program príjme byte ktory inkrementuje a následne odošle naspäť. Tj. ak prijme 1, pošle 2, ak prijme a pošle b a pod...

#include <avr/io.h> 
#include <avr/interrupt.h>

/* obsluha prerusenia pri prijme bytu zo serioveho kanala */
ISR(USART_RXC_vect)
{
    char tmp;
    
    /* hodnota prijateho bajtu sa inkrementuje a posle naspat */
    tmp = UDR;
    UDR = ++tmp;
}

/* obsluha prerusenia pri odoslani bajtu */
ISR(USART_TXC_vect)
{
    /* prazdna instrukcia, nic sa nevykona */
    __asm__ volatile("nop");    

    /* toto je len demonstracia ako vyzera obsluha
       prerusenia pri vysielani
    */
}

int main()
{
    /* 9600 Bd */
    UBRRH = 0;
    UBRRL = 12;

    /* bit dvojnasobnej prenosovej rychlosti */
    UCSRA = _BV(U2X);
    /* zapne sa prijimac, vysielac a prerusenia pri prijme a vysielani */
    UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE) | _BV(TXCIE);
    /* 8 datovych bitov ramca, ostatne nastavenia su default */
    UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);

    /* povolenie globalneho prerusenia */
    sei();

    /* programova slucka */
    for(;;) 
    {
	/* toto je skor demonstracia ako sa daju v C
	   vkladat prikazy assemblera :-)
	   NOP - No OPeration - instrkcia nic nerobi 
	*/
         __asm__ volatile("nop");
    }

    return 0;
}

Soubor:terminal_priklad2.png

[editovat] Ovládanie LEDiek/stav tlačítok

Program na začiatku vypíše na terminále inštrukcie pre uživateľa. Spočiatku sú všetky LEDky zhasnute. Voľbou 1 až 8 zasvieti jednu z LEDiek, voľbou 0 všetky LEDky zhasnú. LEDky sú pripojene na port B, svietia ak je na pine log. 0. Na pine PD2, čo je vstup externého prerušenia INT0 je pripojené tlačitko voči zemi. Jeho stlačením sa vyvolá prerušenie a program pošle na terminál hlásenie, že bolo stlačené tlačidlo. Reťazce ktoré sa vypisujú sú umiestnené v programovej pamäti (FLASH) mikrokontroléra.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

/* vypisanie retazca z programovej pamate na seriovy kanal */
void vypis(char *data)
{
    while (pgm_read_byte(data) != 0x00)
    {
	UDR = pgm_read_byte(data);
	while((UCSRA & _BV(UDRE)) == 0);
	data++;
    }	
}

/* obsluha prerusenia externeho prerusenia INT0 */
ISR(INT0_vect)
{
    vypis(PSTR("Bolo stlacene tlacidlo!\n"));
}


/* obsluha prerusenia ser. kanalu pri prijme bajtu */
ISR(USART_RXC_vect)
{
    char prijate = UDR;

    /* podla volby sa rozsvieti prislusna LED na porte B */
    switch (prijate)
    {
	case '0': PORTB = 0xFF; break;
	case '1': PORTB = 0xFE; break;
	case '2': PORTB = 0xFD; break;
	case '3': PORTB = 0xFB; break;
	case '4': PORTB = 0xF7; break;
	case '5': PORTB = 0xEF; break;
	case '6': PORTB = 0xDF; break;
	case '7': PORTB = 0xBF; break;
	case '8': PORTB = 0x7F; break;
	default: vypis(PSTR("Zla volba!\n")); break;
    }
}


int main()
{
    /* nastavenie serioveho kanala 9600 Bd, 8 dat. bitov, ziadna parita, 1 stop bit */
    UBRRH = 0;
    UBRRL = 12;
    UCSRA = _BV(U2X);  
    UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE);
    UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);

    /* na porte B su pripojene LEDky, svietia v log. 0 */
    DDRB = 0xFF;
    PORTB = 0xFF;

    /* externe prerusenie INT0, aktivne pri zostupnej hrane */
    /* na PD2 je zapnuty pull-up */
    DDRD |= _BV(PD2);
    PORTD |= _BV(PD2);
    MCUCR |= _BV(ISC01);
    GICR |= _BV(INT0);
	
    /* globalne povolenie prerusenia */
    sei();

    /* informacne spravy */
    vypis(PSTR("INPUT/OUTPUT RS-232 demo\n"));
    vypis(PSTR("Zadaj cislo LEDky (1-8, 0 je zhasnut vsetko):\n"));

    while (1)
    {
	/* hlavna programova slucka */
    }

    return 0;
}

Soubor:terminal_priklad3.png

[editovat] Záver

Popisovaná problematika sériovej komunikácie AVR-ka s PC je celkom rozsiahla. V práci som sa snažil naznačiť nevyhnutné poznatky a demonštrovať ich na jednoduchých príkladoch. Dúfam že táto práca bude pre niekoho užitočná a získané poznatky aplikuje do reálnych zariadení.

[editovat] Odkazy

[1] http://www.atmel.com/atmel/acrobat/doc2466.pdf - datasheet Atmel ATmega16
[2] http://www.nongnu.org/avr-libc/ - manuál k C pre AVR
[3] http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf - datasheet k FT232R
[4] https://sites.google.com/site/terminalbpp/ - program Terminal pre Windows
[5] http://ap.urpi.fei.stuba.sk/ap/blok3.php - Komunikácia so sériovým portom v jazyku C pod Windows

Osobní nástroje