Laboratorio: SPI

SPI: Arduino master e slave

In questa pagina Arduino è utilizzato come master e come slave SPI. L'obbiettivo è analizzare i segnali trasmessi con un oscilloscopio dotato di strumenti di decodifica dei segnali seriali, per esempio Picoscope 3405A prodotto da Pico Technology. Per chi non dispone di tale strumento, a fondo pagina sono presenti alcuni esempi.

Attività 1

Per questa prima attività ci servirà solo Arduino che useremo  come master, senza collegare alcuna periferica; ci limiteremo ad osservare con l'oscilloscopio i segnali MOSI, CLK e SS durante la trasmissione di un byte.

Il software farà uso delle librerie SPI.

Il codice dovrà inizialmente configurare SPI (SPISettings()), possibilmente all'interno di beginTransaction(). Prima di trasmettere il singolo byte occorrerà inoltre attivare SS (un pin qualunque, in genere attivo basso) e appena terminata la trasmissione disattivarlo.

Il byte letto è casuale, non essendoci nessun segnale collegato a MISO.

Cosa succede se si collega direttamente MISO a MOSI (loopback)?

Attività 2

Collegare una periferica SPI ed analizzare i segnali scambiati. Ovviamente librerie e procedure dipendono dal tipo di dispositivo utilizzato; qui, per esempio, è utilizzato nRF24L01+.

I segnali SPI sono presenti anche sul connettore GPIO di Raspberry Pi. La scheda RPi demo può ospitare due dispositivi SPI: un ADC ed un modulo a radiofrequenza nRF24L01+, ciascuno collegato ai due SS presenti sul connettore GPIO.

Attività 3

Collegare due Arduino, uno configurato come controller ed uno come periferica, e trasmettere dati in modo bidirezionale. L'immagine di apertura mostra due Arduino Nano collegati tra di loro.

Il collegamento è tra pin omonimi, senza "incrociare" nulla:

La parte complessa è scrivere il codice per l'Arduino che assume il ruolo di periferica: non esistono infetti librerie standard che permettono ciò. Di seguito un codice minimale (nota 3) e, a seguire, una breve spiegazione delle criticità.

#include<SPI.h>
volatile boolean datoPronto;
volatile byte ricevutoDalController;
byte risposta;

void setup() {
 Serial.begin(115200);
 pinMode(MISO, OUTPUT);
 pinMode(MOSI, INPUT);
 pinMode(SS, INPUT);
 pinMode(SCK, INPUT);
 SPCR = SPCR | (1 << SPE);
 datoPronto = false;
 SPI.attachInterrupt();
}

ISR (SPI_STC_vect) {
 ricevutoDalController = SPDR;
 datoPronto = true;
}

void loop() {
 if (datoPronto) {
  Serial.print("Byte trasmesso: ");
  Serial.println(risposta);
  Serial.print("Byte ricevuto dal controller: ");
  Serial.println(ricevutoDalController);
  Serial.println();
  datoPronto = false;
  SPDR = risposta--;
 }
}

I/O

I pin dei segnali devono essere configurati manualmente come ingressi ed uscite, in base al verso dei segnali mostrato in questo schema, in pratica il contrario di quando fatto automaticamente dalle librerie SPI.

Il registro SPCR

Il modulo SPI di Arduino è controllato dal registro a 8 bit SPCR (nota 2):

Per i nostri scopi sono significativi i seguenti bit:

Possiamo lasciare al valore di default (0) DORD, CPOL e CPHA se, come in genere avviene, vogliamo utilizzare MSBFIRST e SPI_MODE0.

Attiveremo l'interrupt (SPIE) con l'apposito metodo

I due bit che gestiscono il clock sono ignorati in quanto il clock è generato dal controller.

Interrupt

Come in genere avviene nei programmi che ricevono dati in modo asincrono, la ricezione è gestita interamente dall'hardware che avverte con un interrupt (nota) la presenza di un nuovo dato.

Le ISR (Interrupt Service Routine) di Arduino sono individuate dalla parola chiave ISR e sono vettorizzate, cioè ne esiste una diversa per ciascuna periferica. Essa viene "agganciata" all'hardware con il metodo attachInterrupt().

Da notare che le variabili globali modificate all'interno della ISR sono definite come volatili.

Il registro SPDR

Questo registro è utilizzato in due modi:

L'immagine seguente mostra i segnali SPI visti con un oscilloscopio e la relativa decodifica:

Altre attività

Segnali esemplificativi

Il file SPI.zip contiene quattro diversi esempi da utilizzare con la versione demo di Picoscope. Per tutti sono visibili i segnali MISO, MOSI (nota 4), Clock e SS:

  1. Frame costituito da un solo byte, MODE0
  2. Cinque frame ciascuno costituito da un singolo byte, MODE0
  3. Due frame costituiti da tre byte ciascuno, MODE0
  4. Tre frame (l'ultimo parziale, costituiti da un solo byte. MODE2

Note

  1. Il master può utilizzare un pin qualunque come SS, la periferica deve necessariamente usare il pin che porta questo nome
  2. https://docs.arduino.cc/...serial-peripheral-interface
  3. Questo codice è specifico per l'architettura ATMega
  4. MISO e MOSI non sempre sono distinguibili se non si dispone dello schema elettrico. A volte, non sempre, MISO è riconoscibile dal fatto che, quando SS è disattivato, viene configurato come 3-state, cioè né alto, né basso


Pagina creata nel marzo 2022
Ultima modifica: 1 maggio 2022


Licenza "Creative Commons" - Attribuzione-Condividi allo stesso modo 3.0 Unported


Pagina principaleAccessibilitàNote legaliPosta elettronicaXHTML 1.0 StrictCSS 3

Vai in cima