Sunteți pe pagina 1din 10

Lucrare de Laborator CD – Nr.

CONCEPTUL DE MAGISTRALA SPI

1. Introducere

1.1 Scopul lucrării


Scopul lucrării este de a familiariza studenții cu aspectele practice de baza pentru utilizarea în
aplicații de comunicații de date folosind interfata SPI.

1.2 Utilizarea magistralei SPI


Magistrala SPI (Serial Peripheral Interface), dezvoltată de Motorola, este o interfață de
comunicare serială sincronă (ca si I2C) folosită pentru comunicarea la distante foarte reduse ce
opereaza în mod full-duplex(transferul de date are loc în ambele direcții simultan). Device-urile
comunică folosind o relație de tipulmaster - multi slave (nu sunt suportati mai multi masteri),
master-ul fiind cel care inițiază frame-urile dedate.
SPI se mai numeşte si "four wire" serial bus pentru a-l deosebi de celelalte standarde ce folosesc
1, 2sau 3 fire. Cele patru fire utilizate in comunicație sunt:

SCLK — Serial Clock (output from master)


MOSI/SIMO — Master Output, Slave Input (output from master)
MISO/SOMI — Master Input, Slave Output (output from slave)
SS — Slave Select (active low; output from master)

Fig. 1 Relație Master – Slave

Fig. 2 Relație Master – Multi Slave


Lucrare de Laborator CD – Nr. 5

2. Breviar Teoretic – Protocolul de transfer pe magistrala SPI


Într-o comunicaţie SPI masterul este cel care iniţiază comunicaţia prin setarea linieiSS pe 0
(enable Slave Select). In prealabil masterul trebuie să se asigure că frecvenţa setată ceasului este
suportată de către slave.

Fig. 3 – Exemplu comunicaţie SPI

Perifericul slave utilizează semnalul de ceas (SCK) pentru achiziţia de date (fluxul de biţi
transmişi serial de către master). După cum am precizat încă din partea introductivă comunicaţia
SPI este o comunicaţie full duplex:

- master-ul trimite un bit pe linia MOSI care este citit de către slave de pe aceeaşi linie;
- slave-ul trimite un bit pe linia MISO care este citit de către master de pe aceeaşi linie;

Fig. 4 – Registrii Master/Slave


Lucrare de Laborator CD – Nr. 5

Transferul propriu-zis de date folosind protocolul SPI implică doi regiştrii de deplasare serială a
datelor (serial shift registers), unul pentru master şi unul pentru slave interconectaţi ca în figura
4. Masterul începe transmisia unui octet prin scrierea acestuia în registrul său de deplasare.
Deplasarea se începe cu bitul cel mai semnificativ (MSB) pe liniile MOSI moment în care un
nou bit este adaugat pe pozitia cea mai puţin semnificativă (LSB) din registru. Pe masură ce se
face transmisia către slave (prin MOSI), slave-ul începe la randul său să transmită date din
registrul său de deplasare (prin MISO) către master. În acest fel se face schimbul de informaţii
între cele 2 registre seriale de deplasare. După ce întreg cuvântul a fost transmis, master-ul şi
slave-ul au interschimbat valorile din cei doi regiştrii; dacă mai există date de transmis procesul
se repetă.
Când nu mai există date de transmis masterul va întrerupe generarea semnalului de ceas şi va
pune linia SS destinată slave-ului respectiv pe 1.

În cazul unei comunicaţii Master – Multi Slave, selectarea slave-ului de către master se face prin
intermediul liniei SS. Slave-urile neselectate de către master nu vor lua parte la comunicaţie –
vor ignora semnalele de pe SCK şi MOSI şi nu vor transmite nimic pe MISO.
Master-ul poate selecta doar un slave la un moment dat.

3. SPI vs I2C

Protocoalele SPI şi I2C sunt folosite pentru comunicaţia între circuite integrate şi periferice la
viteze de transfer scăzute. În următorul tabel este prezentată o comparaţie între cele 2 standarde
de comunicaţie:

Caracteristici SPI I2C


Tipul magistralei Single Master – Multi Slave Multi Master – Multi Slave
Tip de comunicaţie Full duplex Semi-duplex
Rata de transfer Mare Mică
Viteze de transmisie Nu e definită o limită (uzual 1Mbps – 3.4Mbps
10Mbps)
Format mesaj (date) Mesaje de orice lungime Limitare la 8 biţi (pachete a cate
un octet urmate de un ACK)
Numar fire 4 2
Adresare device-uri Fără suport de adresare (se 7 biţi alocaţi pentru adresare
foloseşte linia SS)
Control flow Nu Da (atât pentru SCL cât şi
pentru SDA)
Acknowledgement Nu există - master-ul poate Da – după fiecare byte urmează
transmite în gol un bit de ACK
Lucrare de Laborator CD – Nr. 5

4. Parte Practică
4.1 Componente necesare
- Arduino Uno
- SPI Bus Serial EEPROM (25LC040A)
- Breadboard + fire pentru realizarea legăturilor

Circuitul 25LC040A

Circuitul 25LC040A este un circuit de EEPROM(electrically erasable programmable read-only


memory), acesta are ca scop păstrarea datelor şi în cazul unei pierderi a tensiunii de alimentare.

Cricuitul prezintă următoarele caracteristici:

 Interfata SPI
 Max. clock 10 MHz
 Organizare 512 x 8-bit
 Mod de scriere pe pagină(până la 16 bytes)
 Protecţie pentru suprascrierea datelor
 Număr de ciclii de ştergere/scriere: 1,000,000 Erase/Write cycles
 Perioada de reţinere a datelor : > 200 ani
Pentru varianta DIP avem următorul pin layout

Descrierea acestora este dată de următorul tabel:


Lucrare de Laborator CD – Nr. 5

Schema bloc a circuitului este următoarea:

Comenzile suportate de circuit sunt:

Pentru efectuarea operaţiei de scriere trebuie data comanda de WREN(write enable)

Scrierea unui octet trebuie să urmeze secvenţa:


Lucrare de Laborator CD – Nr. 5

Citirea unui octet se face conform diagramei de mai jos:

Descrierea completă a circuitului se găseste în următorul document:


http://ww1.microchip.com/downloads/en/DeviceDoc/21827C.pdf

4.2 Cerinţe

Să se realizeze o scriere urmată de o citire a unei secvenţe de date (pe baza unor comenzi
recepţionate de pe interfaţa serială) de la un Arduino Uno la o memoria flash EEPROM
(25LC040A) pe baza exemplului următor:
#define MOSI 11 //MASTER OUT SLAVE IN
#define MISO 12 //MASTER IN SLAVE OUT
#define SPICLOCK 13 //MASTER CLOCK OUTPUT
#define SLAVESELECTEEPROM1 10 // SLAVE SELECT CHIP EEPROM 1

#define WREN 6 //Activare scriere pentru EEPROM


#define WRDI 4 //Dezactivare scriere pentru EEPROM
#define READ 3 //Operatie citire EEPROM
#define WRITE 2 //Operatie scriere EEPROM

#define SSTRANSITIONDELAY 10
#define WRITEDELAY 1000

//Variabile pentru datele de intrare/iesire EEPROM


Lucrare de Laborator CD – Nr. 5

byte eeprom_output_data=0;
byte eeprom_input_data=0;

//Adresa de scriere/citire
int address=7;

//Valori pentru scriere


char valEEPROM1=25;

String inputString = ""; // Variabila pentru stocarea comenzii


boolean stringComplete = false; // Comanda finalizata

//Functie pentru transferul datelor


char spi_transfer(volatile char data)
{
SPDR = data; // Incarcare date
while (!(SPSR & (1<<SPIF))){} // Pooling pentru a asigura transferul
complet al datelor
return SPDR; // recuperarea datelor citite
}

//Functie pentru citirea EEPROM1


byte read_eeprom1(int EEPROM_address)
{

int data; //Variabila temporara pentru


stocarea datelor citite
digitalWrite(SLAVESELECTEEPROM1,LOW); //Activare circuit EEPROM 1
delay(SSTRANSITIONDELAY);
spi_transfer(READ); //Transmisie comanda citire
spi_transfer((char)(EEPROM_address>>8)); //Transmisie adresa MSB first
spi_transfer((char)(EEPROM_address)); //Transmisie adresa
data = spi_transfer(0xFF); //Receptie caracter
delay(SSTRANSITIONDELAY);
digitalWrite(SLAVESELECTEEPROM1,HIGH); //Dezactivare EEPROM 1
return data;
}

//Functie pentru receptionarea datelor pe interfata seriala


void serialEvent() {
while (Serial.available()) {
// citire caracter cu caracter
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
//activare conditie procesare
if (inChar == '\n') {
stringComplete = true;
}
Lucrare de Laborator CD – Nr. 5

}
}

void handleMemoryOperation(String data)


{
switch(data[0])
{
case '0':
digitalWrite(SLAVESELECTEEPROM1,LOW); //enable device
delay(SSTRANSITIONDELAY);
spi_transfer(WREN); //write enable
digitalWrite(SLAVESELECTEEPROM1,HIGH); //disable device
delay(SSTRANSITIONDELAY);
digitalWrite(SLAVESELECTEEPROM1,LOW); //enable device
spi_transfer(WRITE); //write instruction
spi_transfer((char)(address>>8)); //send MSByte address first
spi_transfer((char)(address)); //send LSByte address
spi_transfer((char)valEEPROM1); //write data byte
digitalWrite(SLAVESELECTEEPROM1,HIGH); //disable device
//wait for eeprom to finish writing
delay(WRITEDELAY);
digitalWrite(SLAVESELECTEEPROM1,LOW); //enable device
delay(SSTRANSITIONDELAY);
spi_transfer(WRDI); //write disable
digitalWrite(SLAVESELECTEEPROM1,HIGH); //disable device
Serial.println("Write done");
break;
case '1':
eeprom_output_data = read_eeprom1(address);
Serial.print("EEPROM1 data: ");
Serial.println(eeprom_output_data,DEC);
break;
default:
break;
}
}

//Inializarea sistemului
void setup()
{
Serial.begin(9600); //Initializarea interfata seriala
inputString.reserve(10); //Alocare date comanda
pinMode(MOSI, OUTPUT); //Configurare pin iesire
pinMode(MISO, INPUT); //Configurare pin intrare
pinMode(SPICLOCK,OUTPUT); //Configurare pin iesire
pinMode(SLAVESELECTEEPROM1,OUTPUT); //Configurare pin iesire

digitalWrite(SLAVESELECTEEPROM1,HIGH); //Dezactivare EEPROM 1


Lucrare de Laborator CD – Nr. 5

// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 rate (fastest)
SPCR = (1<<SPE)|(1<<MSTR);
byte clr; //Variabila temporara pentru
curatarea registrelor SPE si MSTR
clr=SPSR; // "Curatarea" registrului SPSR
clr=SPDR; // "Curatarea" registrului SPDR

void loop()
{
if (stringComplete) {
Serial.print("Received command: ");
Serial.println(inputString);
//Alegere operatie
handleMemoryOperation(inputString);
// Resetare variabile globale
inputString = "";
stringComplete = false;
}

Realizaţi o structura Master – Multi Slave (Arduino – 2 memorii EEPROM) şi pe baza unor
comenzi date să se facă scrirea/citirea din cele 2 memorii:

0 - scriere date circuit 1


1 - citire date circuit 1
2 - scriere date circuit 2
3 - citire date circuit 2

Utilizând analizoarele Saleae să se monitorizeze liniile SPI: SCK, MOSI, MISO, SS.

Proiect
Să se implementeze un sistem Single Master – Multi Slave pentru citirea şi scrierea datelor din
două memorii EEPROM (25LC040A) pe baza protocolului definit mai jos:

Operaţie Separator Identificator_Slave Separator Adresa Separator Valoare

Operaţie: 0 – scriere, 1 – citire


Identificator_Slave: 0 – slave 0, 1 – slave 1
Lucrare de Laborator CD – Nr. 5

Adresa: adresa de scriere in EEPROM


Valoare: valoarea transmisa pentru scriere in EEPROM (în cazul citirii se va trimite valoarea
0xFF)
Separator: caracterul „-”

Exemplu: 0_1_25_12 – se va face o scriere în memoria slave 1, la adresa 25, valoarea 12

S-ar putea să vă placă și