Reklama

USART u AVR 3. Díl – Praktické ukázky II

Úvod

V předchozích dílech o jednotce USART mikrokontrolérů AVR jsme si řekl teoretické poznatky (můžete ho najít ZDE), vyzkoušeli jsme si základní pracovní režimy (ke shlédnutí ZDE) a nyní je na řadě ukázat si, jak používat multi procesorovou komunikaci a synchronní režim.
 
Z výčtu vzorových zdrojových kódů, který lze nalézt v prvním díle, si ukážeme následující:

  • USART – Komunikace procesor – procesor
  • USART – MPCM (Multi-processor Communication Mode)
  • USART – Synchronní režim
USART – komunikace procesor – procesor

Kromě běžných 8bitových (a kratších) zpráv můžeme na AVR posílat USARTem i 9bitovou zprávu. Protože však nemáme prostředky jak ji přijímat v PC (zmiňované moduly v prvním díle to neumožňují), předvedeme si takovou komunikaci mezi dvěma mikrokontroléry. Zabijeme tak dvě mouchy jednou ranou, protože v jednom příkladě budeme mít kód pro příjem i pro vysílání. Komunikaci mezi mikrokontroléry si předvedeme pouze jednosměrnou. Jeden mikrokontrolér (Master) bude hlídat stisk tří tlačítek. Po stisku některého z nich pošle zprávu druhému mikrokontroléru (Slave), který podle příchozí zprávy rozsvítí nebo zhasne příslušnou LED diodu. Připravíme si tím podhoubí pro další příklad (s použitím MPCM). Navíc si ukážeme, jak na straně přijímače zachytit některou z chyb přenosu. Master má zdrojový kód ZK2. Přenosovou rychlost nastavíme na 9600 Bd, zvolíme jeden stop bit a žádnou paritu. Délku zprávy na 9 bitů zvolíme nastavením bitů UCSZ2 (v registru UCSRB) a dvojicí bitů UCSZ1 a UCSZ0 (v registru UCSRC). Devátý bit zprávy je před odesláním nutné nahrát do bitu TXB8 v registru UCSRB. To je také jediná modifikace, kterou v naší funkci odesli() provedeme. Zbytek kódu je bez záludností. K programu mikrokontroléru – Slave (zdrojový kód ZK1) budu mít více komentářů. Konfigurace USART je shodná jako s Masterem. Přijímací funkci USART_prijem() napíšeme hloupě pomocí “pollingu”, abyste nebyli zbytečně zmatení. Čekáme v ní, dokud není přijata zpráva (což poznáme nastavením bitu RXC). Ještě před přečtením dat z UDR je nutné přečíst stav UCSRB, protože v něm je devátý bit zprávy. Přečtením UDR by hodnoty v UCSRB pozbyly platnost a my bychom už neměli možnost bit přečíst. To samé platí pro registr UCSRA, ve kterém jsou vlajky indikující stav přenosu. Teprve pak můžeme UDR přečíst a uvolnit tak registr k příjmu další zprávy. Zkontrolujeme tři stavové bity, zda některý z nich není v log.1. Bit DOR (Data OverRun) signalizuje, zda jsme si stihli vyzvednout včas všechny příchozí zprávy, nebo zda byl buffer plný a některá ze zpráv je ztracena. Bit FE (Frame Error) signalizuje korektní příjem stop bitu. Pokud by stop bit nepřišel tak jak má, tak máme důvod myslet si, že je přenos porušen. Ať už tím, že vysílač vysílá na jiné rychlosti, nebo byla linka rozpojena. Bit PE (Parity Error) by pak signalizoval chybu parity. Protože ale paritu ve zprávě neočekáváme, tak nás nebude tento bit zajímat. Pokud by některý z těchto bitů byl nastaven, necháme funkci vrátit hodnotu 0xffff, čímž dáme hlavní smyčce na vědomí, že nastal problém. Ta na to později zareaguje rozsvícením příslušné LED diody. Pokud byl příjem v pořádku a žádný z chybových bitů není nastaven, tak složíme 9bitovou zprávu do “integeru” a přijímací funkce ji vrátí. Hlavní smyčka už pak zprávu roztřídí. Pokud přišla hodnota 0x101, tak se rozsvítí LED dioda a pokud přišla hodnota 0x103, tak se zhasnou všechny LED diody včetně té, která signalizuje chybný přenos. Oba mikrokontroléry pracují na 8 MHz (jak je vidět v záhlaví zdrojového kódu). Mikrokontrolér Master je připojen svým vývodem Tx na Rx mikrokontroléru Slave. Slave má indikační LED na pinech PB0 a PB1. Master má tlačítka na pinech PA3, PA4 a PA5. Chybnou zprávu si můžete nasimulovat prostě tím, že odpojíte datovou linku od Mastera a připojíte ji na zem. Jakmile se na pin Rx dostane log. 0 vyhodnotí to přijímač jako začátek vysílání, poté přijme domnělou zprávu a na jejím konci bude očekávat stop bit (log. 1), který ale neobdrží, protože je linka pevně připojena na zem. To vyhodnotí jako “Frame Error” a dá vám o tom vědět rozsvícením LED.

 

001: // ZK1: 9bit multiprocesorová komunikace 1 – Slave
002: #include <avr/io.h>
003: #define F_CPU 8000000
004:
005: unsigned int USART_prijem(void);
006: volatile unsigned int x=0;
007:
008: int main(void){
009: UBRRH = 0;
010: UBRRL = 51;// podle tabulky pro clock 8MHz a baud rate 9600Bd/s
011: // zapnout vysílač, 9bit zpráva
012: UCSRB = (1<<RXEN) | (1<<UCSZ2);
013: // 1 stop bit,žádná parita;
014: UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
015: // výstupy na indikační LED
016: DDRB = (1<<DDB0) | (1<<DDB1);
017:
018: while(1){
019: x = USART_prijem();// čekej než přijde znak
020: // rozsviť LED1
021: if(x == 0x101){PORTB |= (1<<PORTB0);}
022: // zhasni obě LED
023: if(x == 0x103){PORTB &=~((1<<PORTB1) | (1<<PORTB0));}
024: // rozsviť LED2 – chyba přenosu
025: if(x == 0xffff){PORTB |= (1<<PORTB1);}
026: }
027: }
028:
029: unsigned int USART_prijem(void)
030: {
031: unsigned char stav, resh, resl;
032: while ( !(UCSRA & (1<<RXC)) );// čekej dokud není dokončen příjem
033: stav = UCSRA;// ulož vlajky přijímače (Frame error, Overrun
034: // a Parity error)
035: resh = UCSRB;// vytáhni 9.bit zprávy (musí být před čtením UDR !)
036: resl = UDR;// vytáhni dolních 8 bitů zprávy
037: // pokud něco nehraje
038: if (stav & ((1<<FE) | (1<<DOR) | (1<<PE))){return -1;}
039: resh = (resh >> 1) & 0x01;// odfiltruj 9.bit zprávy
040: return ((resh << 8) | resl);// vrať 9bitovou hodnotu
041: }

 

 

001: // ZK2: 9bit multiprocesorová komunikace 1 – Master
002: #include <avr/io.h>
003: #define F_CPU 8000000
004: #include <util/delay.h>
005:
006: // makro na kontrolu stavu tlačítka
007: #define STISKNUTO_A (!(PINA & (1<<PINA3)))
008: // makro na kontrolu stavu tlačítka
009: #define STISKNUTO_B (!(PINA & (1<<PINA4)))
010: // makro na kontrolu stavu tlačítka
011: #define STISKNUTO_C (!(PINA & (1<<PINA5)))
012:
013: char stav_tlacitka_a=1,stav_tlacitka_b=1,stav_tlacitka_c=1;
014: void odesli(unsigned int data);// odesílání 9bitové zprávy
015:
016: int main(void){
017: UBRRH = 0;
018: UBRRL = 51;// podle tabulky pro clock 8MHz a baud rate 9600Bd/s
019: // zapnout vysílač, 9bit zpráva
020: UCSRB = (1<<TXEN) | (1<<UCSZ2);
021: // 1 stop bit,žádná parita;
022: UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
023: // vstup pro tlačítka
024: DDRA &= ~((1<<DDA4) |(1<DDA3) | (1<DDA5));
025: // pull-up na tlačítka
026: PORTA |= (1<<PORTA4) | (1<<PORTA5) | (1<<PORTA3);
027:
028: while(1){
029: // sleduj stisk tlačítek a po stisku odešli zprávu
030: if(STISKNUTO_A && stav_tlacitka_a){
031: stav_tlacitka_a = 0;
032: odesli(0x101);
033: }
034: if(STISKNUTO_B && stav_tlacitka_b){
035: stav_tlacitka_b = 0;
036: odesli(0x006);
037: }
038: if(STISKNUTO_C && stav_tlacitka_c){
039: stav_tlacitka_c = 0;
040: odesli(0x103);
041: }
042: // tlacitka byla uvolnena
043: if(!(STISKNUTO_A || STISKNUTO_B || STISKNUTO_C)){
044: stav_tlacitka_a=1;stav_tlacitka_b=1;stav_tlacitka_c=1;}
045: _delay_ms(100);// ošetření zákmitů tlačítek
046: }
047: }
048:
049: void odesli( unsigned int data ){
050: while (!( UCSRA & (1<<UDRE)));// čekej dokud není buffer volný k zapsání nových dat
051: UCSRB &= ~(1<<TXB8);// vyčisti 9.bit zprávy
052: // a pokud má být nastaven, nastav ho
053: if ( data & 0x0100 ){UCSRB |= (1<<TXB8);}
054: UDR = data;// zapiš dolních 8bitů zprávy a odešli ji
055: }
Vzorové zdrojové kódy slouží pouze k jednoduché demonstraci funkce, proto často obsahují globální proměnné, neobsahují většinou ukazatele, dále také neobsahují kontroly proměnných, definování nevyužitých pinů mikrokontroléru a podobné správné programátorské návyky. Proto je nutné tyto kódy brát s patřičnou rezervou.
 

Obr. 1: Vlevo je Slave s indikačními LED, vpravo Master se třemi tlačítky

Obr. 1: Vlevo je Slave s indikačními LED, vpravo Master se třemi tlačítky
USART – MPCM (Multi-processor Communication Mode)

ATmega umí USART používat ve speciálním MPCM módu. Mějme jeden Master a několik Slave mikrokontrolérů. Pokud je všechny propojíte jednou linkou (Masterův Tx pin se spojí s Rx piny všech Slave), může Master dávat pokyny všem Slave mikrokontrolérům. Bohužel ho ale musí všechny Slave poslouchat. Zprávu pro jednoho Slave si musí přečíst všichni ostatní Slave a obtěžuje je to při práci. Zvlášť pokud je komunikace hodně aktivní. MPCM mód slouží právě v takových situacích. Mikrokontrolér v MPCM módu ignoruje všechny příchozí zprávy, které nemají nastavený devátý bit (neztrácí čas jejich dekódováním). Komunikace pak funguje následovně. Master pošle zprávu s nastaveným devátým bitem. Tu poslouchají a zpracovávají všechny Slave mikrokontroléry. V ní pošle “adresu” (identifikační číslo) toho Slave, se kterým chce komunikovat. Příslušný Slave si vypne MPCM mód a bude přijímat všechny zprávy. Master mu může dávat pokyny a ostatní neposlouchají. Když chce Master komunikovat s někým jiným, opět pošle zprávu s nastaveným devátým bitem obsahující novou adresu. Všichni Slave opět poslouchají, a pokud jim adresa nepatří, zapnou si MPCM mód a ignorují všechny zprávy opět do té doby, než master odešle další zprávu s nastaveným 9.bitem (adresu). Toť vše. Nikdy jsem tuto možnost v praxi nevyužil, takže z mé strany jde o příklad čistě akademický – jen si chci vyzkoušet, jestli to funguje. Konfigurace je trochu náročnější na hardware. Na rozumnou demonstraci potřebujete alespoň tři mikrokontroléry. Já použil dvakrát ATmega16 a jednou ATmega8, abych alespoň ověřil, že je kód přenositelný, viz Obr. 2. Vysílací program je stejný jako v předchozím příkladě. Jeho konfiguraci tedy není nutné rozebírat. Zdrojáky pro Slave obvody se liší jen v “adrese”, která se nastavuje definicí MOJE_ADRESA. Konfigurace USART je opět 9600 Bd, 1 stop bit, žádná parita, 9bitová komunikace s přerušením od přijímače. Nastavením bitu MPCM v registru UCSRA se Slave ihned po startu přepne do MPCM módu a čeká na příjem zprávy. Rutinu přerušení ale vyvolá jen příjem zprávy s nastaveným devátým bitem. Pokud taková zpráva přijde, zkontroluje Slave, zda odeslaná adresa odpovídá té jeho. Pokud ne, nastaví se do MPCM módu, protože datové zprávy nejsou určeny jemu (vůbec nevadí, pokud už MPCM módu byl). Pokud se adresy shodují, vypne MPCM mód (vynulováním bitu MPCM) a zajistí si tak, že přerušení přijde s každou příchozí zprávou. Pokud přijde zpráva bez nastaveného devátého bitu jen ten Slave, který má vypnuté MPCM ji zaznamená. A bude je zaznamenávat tak dlouho, než Master odešle “adresovací” zprávu s nastaveným devátým bitem a Slave se zase nepřepne do MPCM módu (pokud je odvysílaná adresa odlišná od té jeho). Pro otestování může Master odesílat tři zprávy. Zprávy 0x101 a 0x103 jsou adresovací, protože mají nastavený devátý bit. Jeden Slave má adresu 0x01 a druhý Slave má adresu 0x03. Master tedy odesláním jedné z těchto zpráv aktivuje jeden ze Slave mikrokontrolérů. Master pak může odesílat zprávu 0x06 (bez 9.bitu) tu uslyší jen ten Slave, který má vypnutý MPCM mód. Slave po přijetí takové zprávy přepne logickou úroveň na PB0 (blikne LED diodou) a můžete tak vidět, který ze Slave obvodů vás poslouchá.

 

001: // ZK3: 9bit MPCM – slave 1
002: #include <avr/io.h>
003: #define F_CPU 8000000
004: #include <avr/interrupt.h>
005:
006: #define MOJE_ADRESA 0x01// adresa pro slave1
007:
008: void odesli(unsigned int data);// odesílání 9bitové zprávy
009: volatile char nova_zprava=0;// indikujepříchod nové zprávy
010: volatile char zprava=0;
011:
012: ISR(USART_RXC_vect){
013: char rx_bit,data;
014: rx_bit = UCSRB;// nejprve je potřeba vyčíst stav 9.bitu zprávy
015: data = UDR;// vyčtene dolních 8 bitů zprávy
016: if(rx_bit & (1<<RXB8)){// pokud je to byte s adresou (nastaven 9.bit)
017: if(data == MOJE_ADRESA){
018: UCSRA &= ~(1<<MPCM);// pokud je to moje adresa, zapnu příjem všech dat
019: // (vypnu MPCM)
020: }
021: else{UCSRA |= (1<<MPCM);}// pokud je to cizí adresa, vypnu příjem dat
022: // (zapnu MPCM)
023: }
024: else{// pokud jsou to data, jsou určitě určena mě !
025: zprava = data;// data obsahují zprávu
026: nova_zprava++;// přišla další zpráva
027: }
028: }
029:
030: int main(void){
031: UBRRH = 0;
032: UBRRL = 51;// podle tabulky pro clock 8MHz a baud rate 9600Bd/s
033: // zapnout vysílač, 9bit zpráva, přerušení na příjem
034: UCSRB = (1<<RXEN) | (1<<UCSZ2) | (1<<RXCIE);
035: // 1 stop bit,žádná parita;
036: UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
037: UCSRA |= (1<<MPCM);// sleduj jen zprávy s 9.bitem (adresy)
038:
039: DDRB |= (1<<DDB0);
040: sei();
041:
042: while(1){
043: if(nova_zprava){// pokud přišla nějaká zpráva
044: // pokud je její obsah 0x06 přepni LED
045: if(zprava == 0x06){PORTB ^= (1<<PORTB0);}
046: nova_zprava = 0;// zprávu jsme zpracovali
047: }
048: }
049: }

 

 

001: // ZK4: 9bit MPCM – slave 2
002:
003: // …
004: #define MOJE_ADRESA 0x03// adresa pro slave2
005: // …
006: // zbytek kódu je shodný se slave 1

 

 

001: // ZK5: 9bit multiprocesorová komunikace 1 – Master
002: #include <avr/io.h>
003: #define F_CPU 8000000
004: #include <util/delay.h>
005:
006: // makro na kontrolu stavu tlačítka
007: #define STISKNUTO_A (!(PINA & (1<<PINA3)))
008: // makro na kontrolu stavu tlačítka
009: #define STISKNUTO_B (!(PINA & (1<<PINA4)))
010: // makro na kontrolu stavu tlačítka
011: #define STISKNUTO_C (!(PINA & (1<<PINA5)))
012:
013: char stav_tlacitka_a = 1,stav_tlacitka_b = 1,stav_tlacitka_c = 1;
014: void odesli(unsigned int data);// odesílání 9bitové zprávy
015:
016: int main(void){
017: UBRRH = 0;
018: UBRRL = 51;// podle tabulky pro clock 8MHz a baud rate 9600Bd/s
019: // zapnout vysílač, 9bit zpráva
020: UCSRB = (1<<TXEN) | (1<<UCSZ2);
021: // 1 stop bit,žádná parita;
022: UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
023: // vstup pro tlačítka
024: DDRA &= ~((1<<DDA4) |(1<DDA3) | (1<DDA5));
025: // pull-up na tlačítka
026: PORTA |= (1<<PORTA4) | (1<<PORTA5) | (1<<PORTA3);
027:
028: while(1){
029: // sleduj stisk tlačítek a po stisku odešli zprávu
030: if(STISKNUTO_A && stav_tlacitka_a){
031: stav_tlacitka_a = 0;
032: odesli(0x101);
033: }
034: if(STISKNUTO_B && stav_tlacitka_b){
035: stav_tlacitka_b = 0;
036: odesli(0x006);
037: }
038: if(STISKNUTO_C && stav_tlacitka_c){
039: stav_tlacitka_c = 0;
040: odesli(0x103);
041: }
042: // tlacitka byla uvolnena
043: if(!(STISKNUTO_A || STISKNUTO_B || STISKNUTO_C)){
044: stav_tlacitka_a = 1; stav_tlacitka_b = 1; stav_tlacitka_c = 1;}
045: _delay_ms(100);// ošetření zákmitů tlačítek
046: }
047: }
048:
049: void odesli( unsigned int data ){
050: while (!( UCSRA & (1<<UDRE)));// čekej dokud není buffer volný k zapsání nových dat
051: UCSRB &= ~(1<<TXB8);// vyčisti 9.bit zprávy
052: // a pokud má být nastaven, nastav ho
053: if ( data & 0x0100 ){UCSRB |= (1<<TXB8);}
054: UDR = data;// zapiš dolních 8bitů zprávy a odešli ji
055: }
Vzorové zdrojové kódy slouží pouze k jednoduché demonstraci funkce, proto často obsahují globální proměnné, neobsahují většinou ukazatele, dále také neobsahují kontroly proměnných, definování nevyužitých pinů mikrokontroléru a podobné správné programátorské návyky. Proto je nutné tyto kódy brát s patřičnou rezervou.
 

Obr. 2:  Vlevo je master, zbylé dva obvody jsou Slave.

Obr. 2: Vlevo je master, zbylé dva obvody jsou Slave.
USART – Synchronní režim

Synchronní komunikace má nad asynchronní několik výhod. Zaplatíte daň v podobě jedné linky navíc (linka hodin “clock”) a už se nebudete muset starat o přesnosti hodin. A co víc, budete moci využít vyšších přenosových rychlostí než v asynchronním režimu. V asynchronním režimu musí přijímač během jednoho přenášeného bitu 8x nebo 16x navzorkovat vstupní signál (podle toho jestli je zapnutý režim “double speed”). To je daň za to, aby se dokázal přesně synchronizovat se začátkem vysílání (které může přijít úplně kdykoli). V synchronním režimu Master generuje hodiny a všichni účastníci komunikace (Slave mikrokontroléry) jej přijímají a jejich USART jednotka hodiny využívá k příjmu i vysílání. Pokud čipu nastavíte XCK pin jako výstup a zapnete synchronní přenos, stane se z něj Master. Pokud je XCK pin nastaven jako vstup, tak je mikrokontrolér nastaven jako Slave. XCK piny Masteru a Slave musí být přirozeně propojeny. U Slave nemá nastavení přenosové rychlosti žádný význam, takže hodnota v UBRR se nebere v úvahu. Master generuje hodiny neustále, aby Slave mohl kdykoli odesílat zprávy. Frekvence hodin se odvíjí od hodnoty v UBRR, viz článek USART u AVR 1. Díl Teoretický popis. Master může generovat nejvyšší frekvenci až F_CPU/2, ale Slave potřebuje, aby byla nižší jak 1/4 jeho F_CPU. Takže pokud Slave obvod běží s taktem 8MHz, smíte USART provozovat teoreticky až na 2MHz. Je vhodné mít drobnou rezervu a nepřesáhnout v takovém případě hodnotu 1 MHz. Komunikace pak probíhá tak, že s vzestupnou hranou hodin vysílač mění stav datové linky a se sestupnou hranou hodin přijímač čte stav datové linky, nebo opačně. Variantu si volíte bitem UCPOL v registru UCRSC. Veškerá ostatní konfigurace funguje stejně jako v asynchronním režimu. V našem příkladu si zkusíme synchronní komunikaci s UCPOL = 0 a s přenosovou rychlostí 500k Bd/s. Protože USB <-> UART moduly nezvládají synchronní komunikaci, tak si ji opět předvedeme na dvou mikrokontrolérech ATmega. Master (zdrojový kód ZK7) po startu počká nějaký čas, aby se Slave stihl nastavit. Poté nastaví XCK (PB0) jako výstup a nakonfiguruje režim synchronního přenosu. Odešle první zprávu a pak už jen čeká na odpověď. Jakmile ji obdrží, drobně ji upraví a s malým zpožděním ji zase odešle. Slave (zdrojový kód ZK6) dělá to samé s tím rozdílem, že PB0 má nastaven jako vstup a žádnou prvotní zprávu neodesílá. Master si tedy se Slave budou střídavě povídat. Jeden pošle zprávu druhému a ten mu po chvíli odpoví a my to všechno budeme sledovat osciloskopem.

Obr. 3:  Synchronní komunikace pomocí USART. Tmavě modré jsou hodiny (clock). Je patrné, že data jsou nastavována s náběžnou hranou hodin a při sestupné hraně jsou již stabilní a přijímač je může spolehlivě přečíst. Červená linka je Master a posílá zprávy, Slave na světle modré lince mu odpovídá.

Obr. 3: Synchronní komunikace pomocí USART. Tmavě modré jsou hodiny (clock). Je patrné, že data jsou nastavována s náběžnou hranou hodin a při sestupné hraně jsou již stabilní a přijímač je může spolehlivě přečíst. Červená linka je Master a posílá zprávy, Slave na světle modré lince mu odpovídá.

 

001: // ZK6: Synchronní režim – Slave
002: #include <avr/io.h>
003: #define F_CPU 8000000
004: #include <util/delay.h>
005: #include <avr/interrupt.h>
006:
007: volatile char x = 1, nova_zprava = 0;
008:
009: int main(void){
010: UBRRH = 0;
011: UBRRL = 0; // baudrate nemá u slave význam, vstupní clock musí
012: // být menší jak 1/4 F_CPU
012: // přijímáme i vysíláme
013: UCSRB = (1<<RXEN) | (1<<TXEN);
014: // 1 stop bit, žádná parita, 8bit zpráva, synchronní
015: // operace s UCPOL=0
016: UCSRC = (1<<URSEL) | (1<<UMSEL) | (1<<UCSZ1) | (1<<UCSZ0);
017: UCSRB |= (1 << RXCIE);// povolení přerušení od přijímače
018: sei();
019:
020: while(1){
021: if(nova_zprava){
022: nova_zprava = 0;
023: x= x+1;// pošleme zpět přijatá data o jedničku větší
024: // počkej až budeš moct vysílat
025: while (!( UCSRA & (1<<UDRE)));
026: UDR = x;// odvysílej
027: }
028: }
029: }
030:
031: ISR(USART_RXC_vect){
032: x = UDR;
033: nova_zprava = 1;
034: }

 

 

001: // ZK7: Synchronní režim – Master
002: #include <avr/io.h>
003: #define F_CPU 8000000
004: #include <util/delay.h>
005: #include <avr/interrupt.h>
006:
007: volatile char x = 1, nova_zprava = 0;
008:
009: int main(void){
010: _delay_us(500);// master by měl odeslat svou zprávu až si bude
011: // jist, že jsou všichni slave připraveni
012: DDRB = (1<<DDB0);// XCK jako výstup – jsme master a generujeme clock
013: UBRRH = 0;
014: UBRRL = 7; // baudrate 500Bd/s
015: UCSRB = (1<<RXEN) | (1<<TXEN);
016: // 1 stop bit, žádná parita, 8bit zpráva, synchronní
017: // operace s UCPOL=0
018: UCSRC = (1<<URSEL) | (1<<UMSEL) | (1<<UCSZ1) | (1<<UCSZ0);
019: UCSRB |= (1<&ltRXCIE);// povolení přerušení od přijímače
020: sei();
021:
022: // odešli první zprávu
023: while (!( UCSRA & (1<<UDRE)));
024: UDR = x;
025:
026: while(1){
027: if(nova_zprava){
028: nova_zprava = 0;
029: x = x+1;// pošli zpět přijatá data o jedničku větší
030: _delay_us(20);
031: // počkej až budeš moct vysílat
032: while (!( UCSRA & (1<<UDRE)));
033: UDR = x;// odvysílej
034: }
035: }
036: }
037:
038: ISR(USART_XC_vect){
039: x = UDR;
040: nova_zprava = 1;
041: }
Vzorové zdrojové kódy slouží pouze k jednoduché demonstraci funkce, proto často obsahují globální proměnné, neobsahují většinou ukazatele, dále také neobsahují kontroly proměnných, definování nevyužitých pinů mikrokontroléru a podobné správné programátorské návyky. Proto je nutné tyto kódy brát s patřičnou rezervou.
 

 
Autor: Michal Dudka
 

Jiné příspěvky seriálu

 
USART u AVR 1. Díl Teoretický popis
USART u AVR 2. Díl Praktické ukázky I

Tajned facebook
 

Za případné chyby v textu, ve zdrojovém kódě, nebo ve schématickém zapojení se omlouváme.
AUTOŘI NEBEROU ŽÁDNOU ODPOVĚDNOST ZA PŘÍPADNÉ ÚJMY NA ZDRAVÍ ČI MAJETKU.