Laboratorul 5: SPI (Serial Peripheral Interface)

Acest laborator acoperă noțiunea de SPI. Pentru aprofundarea acestui topic, consultați Datasheet ATmega328P și Serial Peripheral Interface.

1. SPI (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:

  • MOSI — Master Output Slave Input (transmiterea datelor de la Master la Slave)
  • MISO — Master Input Slave Output (transmiterea datelor de la Slave la Master)
  • SCLK — Serial Clock (sincronizarea dintre dispozitive. Controlat de Master)
  • CS/SS — Chip Select/Slave Select (selectarea dispozitivului Slave de către Master. Valoarea LOW pentru Slave-ul selectat)

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.

2. Conectarea mai multor dispozitive Slave

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.

3. Conectarea mai multor dispozitive Slave cu ajutorul topologiei SPI Daisy Chain

Î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.

4. Transmiterea datelor cu SPI

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:

  • Dispozitivul Master trimite un bit pe linia MOSI, iar dispozitivul Slave citește acest bit.
  • Dispozitivul Slave trimite un bit pe linia MISO, iar dispozitivul Master citește acest bit.

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.

5. Configurări de SPI

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.

6. SPI în Atmega328p

SPI-ul inclus în microcontrolerul atmega328p poate funcționa atât ca Master, cât și ca Slave.

SPI Control Register (SPCR)

  • Bit 6 - SPE (SPI Enable)
    • 0 - SPI dezactivat
    • 1 - SPI activat
  • Bit 5 - DORD (Data Order)
    • 0 - MSB (din data) trimis primul
    • 1 - LSB (din data) trimis primul
  • Bit 4 - MSTR (Master/Slave Select)
    • 0 - Slave mode
    • 1 - Master mode
  • Bit 3 - CPOL (Clock Polarity)
    • 0 - SCK LOW pe idle (când nu comunică)
    • 1 - SCK HIGH pe idle (când nu comunică)
  • Bit 2 - CPHA (Clock Phase)
    • 0 - datele sunt citite pe frontul de întâmpinare
    • 1 - datele sunt citite pe frontul de sfârșit
  • Bit 1:0 - SPR1:SPR0 (SPI Clock Rate)
    • în modul Master: controlează frecvența SCK-ului.
    • În modul Slave: nu au efect.

SPI Status Register (SPSR)

  • Bit 7 – SPIF (SPI Interrupt Flag)
    • este automat setat pe 1 când transmisia s-a terminat.
  • Bit 0 - SPI2X (Double SPI Speed Bit)
    • în modul Master: când acest bit este setat la 1, viteza SPI (Frecvența SCK) va fi dublată. Aceasta înseamnă că perioada minimă SCK va fi de două perioade de ceas de CPU.
    • în modul Slave:SPI este doar garantat că o să funcționeze la fosc / 4 sau mai mic.

SPI Data Register (SPDR)

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.

Exemplu

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;

7. SPI în Arduino IDE

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);
}

8. Exerciții

  1. Realizați o comunicație prin SPI între 2 plăcuțe Arduino. Hotărâți ce plăcuță va fi Master și care va fi Slave (Câte o echipă poate alege să facă codul pentru Master și cealaltă pentru Slave). Trimiteți un mesaj de la Master către Slave, cât și de la Slave la Master și afișați-le pe interfața serială. Stabiliți o lungime minimă a informației ce trebuie trimisă înainte să opriți transmiterea datelor. Pentru a putea să detectați comunicația SPI din Slave puteți implementa întreruperea SPI_STC_vect (trebuie să adaugați în setup “SPI.attachInterrupt();” - cum trebuiau să fie declarate variabilele modificate în întreruperi?). După ce ați încărcat codul pe plăcuțe, resetați-le pe ambele (apăsând butonul roșu de pe acestea), întâi plăcuța Slave (care va aștepta apoi inițierea comunicației) și apoi plăcuța Master (care va iniția comunicația).
  2. (Bonus) Un card MicroSD este un exemplu de memorie nevolatilă. Pentru ca plăcuța Arduino UNO să poată comunica prin SPI cu cardul, avem nevoie de un adaptor. În privința codului, pe lângă biblioteca “SPI.h” prezentată mai sus avem nevoie și de biblioteca “SD.h” despre care vă sfătuim să citiți înainte să continuați cu exercițiile.
    • a) Scrieți un secret într-un fișier numit “sd.txt” pe cardul SD.
    • b) Faceți schimb de carduri cu colegii voștri și citiți-le secretul.
    • c) Realizați un contor al resetărilor plăcuței Arduino scriind pe cardul SD în fișierul “re.txt” numărul de resetări.

Hint1: La resetare se rulează din nou codul din setup.
Hint2: Salvați pe cardul SD ultima valoare a numărului de resetări.

Dacă ați modificat montajul pentru a realiza exercițiul bonus, refaceți schema exercițiului 1 înainte de a pleca!

/* 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. */
  }
}

9. Resurse

pinout Arduino UNO

Rezolvare
Arhiva cu soluțiile o puteți descărca de aici: lab5-solved.zip

10. Linkuri Utile

pm/lab/lab5-2022.txt · Last modified: 2022/05/01 14:29 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0