Acest laborator acoperă noțiunea de SPI. Pentru aprofundarea acestui topic, consultați Datasheet ATmega328P și Serial Peripheral Interface.
SPI este un standard sincron dezvoltat de Motorola care funcționează în modul full-duplex (transferul de date are loc în ambele direcții simultan). Dispozitivele comunică utilizând o arhitectură Master-Slave (este permis un singur dispozitiv Master și unul sau mai multe dispozitive Slave). Dispozitivul Master este cel care inițiază comunicarea. SPI mai este numit și „four wire”. Cele patru semnale utilizate sunt următoarele:
Putem vedea că există două semnale utilizate pentru transmiterea datelor: MOSI și MISO. Transmiterea datelor pe SPI se face sincron folosind semnalul de ceas SCLK. Semnalul CS / SS este utilizat pentru a selecta dispozitivul slave pe magistrala care este adresată în prezent.
Mai multe dispozitive Slave pot fi conectate în același timp la un singur dispozitiv Master. Semnalele MOSI, MISO și SCLK sunt partajate. Pentru fiecare dispozitiv Slave, dispozitivul Master are câte un semnal CS / SS. Când Masterul dorește să comunice cu un Slave, dispozitivul Master setează pe LOW semnalul CS / SS care duce către dispozitivul Slave dorit (celelalte semnale CS / SS sunt puse pe HIGH). Astfel, dispozitivul Slave cu CS / SS pe LOW știe că Masterul comunică cu el.
În topologia Daisy Chain, datele sunt transferate de la Master la primul Slave, de la primul Slave la al doilea Slave, până când datele ajung la ultimul Slave care le trimite înapoi la Master. Datele primului Slave ajung la Master ultimele, în timp ce datele ultimului Slave ajung la Master primele.
Pentru a începe comunicarea cu dispozitivul Master, ceasul Master-ului trebuie setat la o frecvență cel mult egală cu frecvența suportată de dispozitivul Slave (de obicei până la câțiva MHz). Apoi, Master-ul selectează dispozitivul Slave dorit, punând 0 pe linia CS / SS. În timpul unui ciclu SPI, transmisia este full-duplex:
De obicei, comunicarea SPI implică două registre de șiftare (unul în Master și unul în Slave, conectate circular).
De obicei, primul bit mutat pe MISO / MOSI este cel mai semnificativ bit, în timp ce un bit nou este adăugat la poziția cea mai puțin semnificativă din registru. După ce întregul cuvânt a fost trimis, prin șiftare, Master-ul și Slave-ul au schimbat integral valorile din cele două registre de șiftare. Dacă mai există date de transmis, procesul începe din nou. Când nu există date de transmis, dispozitivul Master întrerupe generarea semnalului de ceas (SCLK) și plasează semnalul CS / SS asociată cu Slave-ul pe HIGH (1 logic). Dispozitivele Slave care nu au fost selectate de semnalul SS asociat vor ignora semnalele de pe SCLK și MOSI și nu vor genera nimic pe MISO. Master-ul poate selecta un singur Slave la un moment dat de timp.
Clock Polarity (CPOL) configurează starea IDLE a ceasului. După cum putem vedea, pentru CPOL = 0, când ceasul este inactiv valoarea semnalului SCLK este pe LOW, iar pentru CPOL = 1 ceasul inactiv are SCLK pe HIGH.
Clock Phase (CPHA) configurează momentul când datele sunt generate pe ieșire și când datele sunt citite la intrare. Pe una dintre fronturile ceasului (de întâmpinare sau de sfârșit) datele sunt generate, iar pe cealaltă datele sunt citite.
Frontul de pornire al ceasului este prima schimbare de ceas. Ex: Pentru un ceas care merge de la LOW la HIGH și înapoi la LOW, frontul de întâmpinare este frontul crescător(tranziția de la LOW la HIGH).
Pentru CPHA = 0 datele sunt generate înainte de frontul de întâmpinare (primul front al ceasului) și sunt citite pe pe frontul întâmpinare (frontul crescător pentru CPOL = 0 și descrescător pentru CPOL = 1).
Pentru CPHA = 1 datele sunt generate pe frontul de întâmpinare (primul front al ceasului) și sunt citite pe frontul de sfârșit (frontul descrescător pentru CPOL = 0 și crescător pentru CPOL = 1).
CPOL și CPHA trebuie setate în conformitate cu configurația dispozitivului SPI cu care comunicăm. De exemplu, dacă UC-ul nostru comunică cu un ADC care utilizează CPOL = 1 și CPHA = 1, este obligatoriu dispozitivul nostru să aibă aceleași configurări de SPI.
SPI-ul inclus în microcontrolerul atmega328p poate funcționa atât ca Master, cât și ca Slave.
Un registru de citire / scriere utilizat pentru transferul de date între Register File și SPI Shift Register. Scrierea în registru inițiază transmiterea datelor. Citirea registrului determină citirea bufferului Shift Register Receive.
Inițializare SPI ca Master.
/* set master mode */ SPCR0 |= (1 << MSTR0); /* set prescaler 16 */ SPCR0 |= (1 << SPR00); /* enable SPI */ SPCR0 |= (1 << SPE0);
Transmiterea unui byte (pe Master).
/* Start transmission */ SPDR0 = data; /* Wait for transmission complete */ while(!(SPSR0 & (1 << SPIF0)));
Recepția unui byte (pe Slave).
/* Wait for reception complete */ while(!(SPSR0 & (1 << SPIF0))); /* Return Data Register */ return SPDR0;
Mediul de dezvoltare Arduino IDE ne oferă posibilitatea de a folosi biblioteca “SPI.h” pentru a facilita comunicarea prin SPI. Mai jos puteți observa un exemplu de cod pentru transmiterea unui byte de date:
/* Exemplu SPI MASTER: transfer un byte către Slave */ #include "SPI.h" void setup(void) { byte masterSend = 1; byte masterRecv; /* Inițializarea pinului de Slave Select */ pinMode(SS, OUTPUT); digitalWrite(SS, HIGH); /* Inițializarea SPI-ului */ SPI.begin(); /* Selectarea Slave-ului */ digitalWrite(SS, LOW); /* Trimiterea byte-ului masterSend către Slave-ul selectat. * Salvarea byte-ului primit de la Slave-ul selectat în masterRecv. */ masterRecv = SPI.transfer(masterSend); /* Deselectarea Slave-ului */ digitalWrite(SS, HIGH); }
/* Exemplu MASTER: Creare și scriere a unui fișier pe Card MicroSD */ #include "SD.h" void setup(void) { File myFile; /* Inițializare comunicare cu Cardul MicroSD. Semnalul SS este pe pinul 4 */ if (SD.begin(4)) { /* Creăm fișierul dacă acesta nu există */ if (!SD.exists("hello.txt")) { myFile = SD.open("hello.txt", FILE_WRITE); if (myFile) { myFile.print("Hello world"); myFile.close(); } else { /* Fișierul nu a putut fi creat. Trebuie investigată problema. */ } } } else { /* Inițializarea comunicării a eșuat. Trebuie investigată problema. */ } }