Master se dá velmi jednoduše SW emulovat (např. pokud regulérní spi piny už využíváme k něčemu jinému). Chceme-li vysílat, prostě jen generujeme hodiny a k nim fázově posunutá data, toť vše. Slave dokonce ani nemusí být procesor, postačí posuvný registr. To může být šikovné např. pro buzení LEDek (shift registr s paralelním výstupem) nebo pro snímaní tlačítek (shift registr s paralelním vstupem).
Jedná se o synchronní komunikaci, přenáší se tedy i hodniny. To kromě vodiče navíc přináší samá pozitiva a sociální jistoty. U takového UARTu se totiž nezávisle generují (nastavují) hodiny u vysílače i přijímače. Tyto hodiny musí být zpravidla danné, přesné a neměnné. Už drobné rozhození časování může vést ke zhroucení celé komunikace. Při SPI generuje hodiny jen MASTER a na jejich kmitočtu a přesnosti nezáleží. Rychlé, pomalé, nejdřív rychlé potom pomalé nebo naopak, nic z toho nám neohrozí komunikaci. S pomalými zařízeními komunikujme pomalu, s rychlými rychle.
Narozdíl od I2C, CAN a dalších se SLAVE nevybírá adresou ale zvláštními vodiči SS (slave select) – viz obrázky. Tím SPI dosahuje nejštíhlejšíhpo možného protokolu, přenáší jen data a v tomto ohledu nemá mezi synchroními kolegy konkurenci. Platí za to daň v podobě SS vodičů navíc, jejich počet je roven počtu SLAVE jednotek v síti.
(Na druhou stranou při vývoji slouží tyto vodiče jako výborný pomocník při odhlalovaní problémů a chyb, máme jednoznačnou identifikaci, který SLAVE je právě vybrán. To je určitě pohodlnější než hledat v posílaných datech adresu SLAVE jednotky. Já osobně pokud budu mít na výběr a najdu nějáký ten volný pin procesoru pro SS vodiče, vždy použiji pro komunikaci s periferií SPI rozhraní.)
Realizace SPI v kódu je poměrně jednoduchá, máme k dispozici jeden společný registr pro vysílání i příjem. Vše je patrné z obrázku nahoře, MASTER zapsáním do registru vydá povel, následně se vygeneruje 8 hodinových cyklů a díky obousměrné komunikaci se provádí příjem i vysílání zároveň. Pokud chceme jenom přijímat, vysíláme zpravidla hodnotu (0×FF), kterou
SLAVE zahodí. Pokud naopak chceme jen vysílat, přijmutá data v registru ignorujeme.
U AVR by pro jednotku MASTER vypadal kód nějak takhle…
funkce pro inicializaci
void SPI_MasterInit(void) { // Set MOSI and SCK output, all others input DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK); // Enable SPI, Master, set clock rate fck/16 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); }
funkce pro vysílání a příjem
unsigned char SPI_MasterTransmit(unsigned char data) { SPDR = data; while ((SPSR & (1<<SPIF)) == 0); return SPDR; }
vysílání
SPI_MasterTransmit('A');
příjem
unsigned char data; data = SPI_MasterTransmit(0xFF);
Žádné komentáře:
Okomentovat