Το πρωτόκολλο επικοινωνίας SPI

Το πρωτόκολλο επικοινωνίας SPI (Serial Peripheral Interface) αρχικά προτάθηκε από την εταιρεία Freescale για να απλοποιήσει τη διαδικασία μεταφοράς δεδομένων μεταξύ ενός μικροελεγκτή και των περιφερειακών συσκευών (ολοκληρωμένα κυκλώματα).

Το SPI πρωτόκολλο επιτρέπει στον μικροελεγκτή να επικοινωνεί σειριακά και με τρόπο σύγχρονο με τις περιφερειακές συσκευές, που σημαίνει ότι χρησιμοποιεί ξεχωριστές γραμμές για τα δεδομένα και για το σήμα ρολογιού, με αποτέλεσμα οι SPI συσκευές να έχουν τέλειο συγχρονισμό.

Επειδή το σήμα ρολογιού στέλνεται μαζί με τα δεδομένα, η δήλωση της ακριβής ταχύτητας μεταφοράς δεδομένων από τις SPI συσκευές δεν είναι σημαντική, μιας που έχουμε μια μέγιστη ταχύτητα που μπορούν να επικοινωνούν οι SPI συσκευές.

Μια SPI συσκευή μπορεί να λειτουργεί σαν αφέντης ή σκλάβος. Όταν μια SPI συσκευή διαμορφωθεί ως αφέντης, τότε αυτή είναι υπεύθυνη για την παραγωγή των παλμών ρολογιού και η SPI συσκευή που διαμορφώνεται ως σκλάβος μπορεί να ανταποκρίνεται μόνο στις αιτήσεις του αφέντη για μεταφορά δεδομένων.

Σε ένα SPI δίαυλο, συνήθως υπάρχει ένας SPI αφέντης ενώ μπορούν να υπάρχουν πολλαπλοί SPI σκλάβοι συσκευές, που με μια γραμμή επιλογής, ο αφέντης επιλέγει εκείνη που θέλει να επικοινωνήσει.

Συνήθως ο μικροελεγκτής διαμορφώνεται σε SPI αφέντη και οι περιφερειακές συσκευές ως SPI σκλάβοι, οι οποίες μπορεί να είναι καταχωρητές ολίσθησης, LED/LCD οδηγοί απεικόνισης, ρολόγια πραγματικού χρόνου, σειριακές μνήμες, ψηφιακά θερμόμετρα, μετατροπείς ADC και DAC, κ.ά.

Οι SPI συσκευές (αφέντης ή/και σκλάβος) χρησιμοποιούν τέσσερα σήματα (ακροδέκτες) τα οποία είναι τα εξής: SCK, MISO, MOSI, SS, τα οποία συνδέονται αγώγιμα μεταξύ των SPI συσκευών (μεταξύ αφέντη και σκλάβου) και συγκεκριμένα εκείνα που έχουν το ίδιο όνομα.

1] Serial clock (SCK). Το SCK σήμα ρολογιού είναι έξοδος από τον αφέντη και είσοδος για τον σκλάβο. Χρησιμοποιείται για το συγχρονισμό της μεταφοράς δεδομένων μεταξύ αφέντη και σκλάβου, που γίνονται πάνω στις γραμμές MOSI και MISO. Το σήμα ρολογιού παράγεται από τον αφέντη και αγνοείται από τους σκλάβους που δεν έχουν ενεργοποιηθεί (επιλεγεί).

2] Master in, slave out (MISO). Αυτό το σήμα είναι έξοδος από τον σκλάβο και είσοδος για τον αφέντη. Χρησιμοποιείται για τη μεταφορά δεδομένων σειριακά από τον σκλάβο στον αφέντη. Ο ακροδέκτης MISO τίθεται σε κατάσταση υψηλής αντίστασης, όταν η SPI συσκευή σκλάβου δεν είναι ενεργοποιημένη (επιλεγμένη).

3] Master out, slave in (MOSI). Αυτό το σήμα είναι έξοδος από τον αφέντη και είσοδος για τους σκλάβους συσκευές. Χρησιμοποιείται για τη μεταφορά δεδομένων σειριακά από τον αφέντη στο σκλάβο.

4] Slave select (SS). Καθώς μια SPI συσκευή διαμορφώνεται ως σκλάβος, αυτός ο ακροδέκτης είναι πάντα είσοδος, το οποίο επιτρέπει την επιλογή του επιθυμητού σκλάβου. Το σήμα SS δεν ελέγχεται από το πρωτόκολλο SPI και θα πρέπει να γράψουμε ξεχωριστό κώδικα για αυτό. Όταν η είσοδος SS της SPI σκλάβου συσκευής οδηγείται σε κατάσταση high ο σκλάβος απενεργοποιείται. Ο επιθυμητός SPI σκλάβος ενεργοποιείται και γίνεται μεταφορά δεδομένα μ’ αυτόν, όταν ο ακροδέκτης εισόδου SS οδηγείται σε κατάσταση low. Ο ακροδέκτης Slave select (SS) στον αφέντη πρέπει να διαμορφώνεται ως έξοδος, αφού επιλέγει τον σκλάβο για SPI επικοινωνία και αν έχουμε πολλαπλούς σκλάβους θα πρέπει να υπάρχουν πολλές γραμμές SS, οι οποίες ελέγχονται από τον κώδικα που θα γράψουμε.

Ο ακροδέκτης SS μπορεί να διαμορφωθεί ως είσοδος στον αφέντη, αλλά για περισσότερα για αυτό το θέμα ανατρέξτε στο datasheet.

Κατά τη μεταφορά δεδομένων, ο μικροελεγκτής (αφέντης) μπορεί να διαμορφωθεί να μεταδίδει το περισσότερο σημαντικό ή το λιγότερο σημαντικό ψηφίο πρώτο. Για τον σκλάβο (ολοκληρωμένο κύκλωμα) που επικοινωνεί με τον μικροελεγκτή, θα μάθετε αν μεταδίδει το περισσότερο σημαντικό ή το λιγότερο σημαντικό ψηφίο, ανατρέχοντας στο datasheet της συσκευής.

Πως το SPI δουλεύει

Η SPI επικοινωνία βασίζεται σε δυο καταχωρητές ολίσθησης, ο ένας στον αφέντη και ο άλλος στον σκλάβο. Επίσης, ο αφέντης παράγει το σήμα ρολογιού, για το συγχρονισμό των καταχωρητών ολίσθησης. Όπως φαίνεται στο σχήμα, η σειριακή έξοδος του αφέντη (ακροδέκτης αφέντη MOSI) συνδέεται στη σειριακή είσοδο του σκλάβου (ακροδέκτης σκλάβου MOSI). Επίσης η σειριακή είσοδος του αφέντη (ακροδέκτης αφέντη MISO) συνδέεται στη σειριακή έξοδο του σκλάβου (ακροδέκτης σκλάβου MISO).

Ο αφέντης παράγει τους παλμούς ρολογιού για τους καταχωρητές ολίσθησης του αφέντη και του σκλάβου. Η είσοδος ρολογιού είναι ακμοπυροδότητη με την ακμή ανόδου ή καθόδου του σήματος ρολογιού. Στο SPI οι καταχωρητές ολίσθησης έχουν μέγεθος οκτώ bit. Αυτό σημαίνει ότι μετά από οκτώ παλμούς ρολογιού τα περιεχόμενα των δυο αυτών καταχωρητών ολίσθησης έχουν ανταλλαχθεί.

Καθώς ο αφέντης θέλει να στείλει ένα byte δεδομένων, τοποθετεί τα δεδομένα στον δικό του καταχωρητή ολίσθησης και παράγει 8 κύκλους ρολογιού. Μετά από 8 παλμούς ρολογιού το byte έχει μεταδοθεί στον καταχωρητή ολίσθησης του σκλάβου. Όταν ο αφέντης θέλει να λάβει ένα byte δεδομένων, ο σκλάβος πρέπει να έχει τοποθετήσει το byte δεδομένων στον δικό του καταχωρητή ολίσθησης και μετά από 8 παλμούς ρολογιού από τον αφέντη, τα δεδομένα λαμβάνονται από τον καταχωρητή ολίσθησης του αφέντη. Πρέπει να σημειωθεί ότι το SPI πρωτόκολλο είναι “full duplex” που σημαίνει ότι στέλνει και λαμβάνει δεδομένα ταυτόχρονα.

Όταν υπάρχουν πολλαπλοί σκλάβοι που οδηγούνται από ένα αφέντη, υπάρχουν δυο τρόποι σύνδεσης. Ο χρήστης μπορεί να διαλέξει την μέθοδο της σύνδεσης όπως φαίνεται στο σχήμα που ακολουθεί.

Σε αυτή την σύνδεση, ο αφέντης επιλέξει ένα SPI σκλάβο για ανταλλαγή δεδομένων, αφήνοντας ανεπηρέαστους τους υπόλοιπους σκλάβους. Ωστόσο υπάρχουν εφαρμογές όπου χρειάζεται ο αφέντης να ανταλλάξει δεδομένα με όλες τους SPI σκλάβους με μιας κάθε φορά, όπως φαίνεται στο σχήμα που ακολουθεί.

Στη τελευταία μέθοδο οι καταχωρητές ολίσθησης σχηματίζουν δακτυλίδι και έτσι ο αφέντης εξοικονομεί ακροδέκτες. Τα δεδομένα του σκλάβου k ολισθαίνουν στο SPI του αφέντη και τα δεδομένα του αφέντη ολισθαίνουν στον σκλάβο 0, τα δεδομένα του σκλάβου 0 ολισθαίνουν στο σκλάβο 1 κ.τ.λ. Με αυτή τη διαμόρφωση ελάχιστος αριθμός ακροδεκτών ελέγχουν ένα μεγάλο αριθμό περιφερειακών συσκευών. Όμως ο αφέντης δεν έχει την ελευθερία να διαλέξει ένα συγκεκριμένο σκλάβο για ανταλλαγή δεδομένων, προτού διανύσουν τους άλλους σκλάβους συσκευές.

Clock polarity and phase in SPI device

Στην SPI επικοινωνία ο αφέντης και όλοι οι σκλάβοι πρέπει να συμφωνούν στο clock polarity και clock phase για να μπορέσουν να ανταλλάξουν δεδομένα. Οι δυο αυτές οι επιλογές ονομάζονται CPOL (clock polarity) και CPHA (clock phase). Όταν CPOL=0 η τιμή της βάσης του σήματος ρολογιού είναι το λογικό 0, ενώ όταν CPOL=1 η τιμή της βάσης του σήματος ρολογιού είναι το λογικό 1. Με τιμή βάσης εννοούμε την τιμή (κατάσταση) του ακροδέκτη του σήματος ρολογιού μόλις αρχίζει η επικοινωνία SPI.

Επίσης ο όρος CPHA=0 σημαίνει δειγματοληψία στην πρώτη, τρίτη, πέμπτη… ακμή του σήματος ρολογιού ενώ CPHA=1 σημαίνει δειγματοληψία στην δεύτερη, τέταρτη, έκτη…, ακμή του σήματος ρολογιού. Σημειώστε ότι όταν η τιμή της βάσης του σήματος ρολογιού είναι το λογικό 0 (CPOL=0) η πρώτη ακμή σήματος ρολογιού είναι ακμή ανόδου και αν η τιμή βάσης του σήματος ρολογιού είναι το λογικό 1 (CPOL=1) η πρώτη ακμή του σήματος ρολογιού είναι ακμή καθόδου.

Βήματα για την εγγραφή δεδομένων σε μια SPI συσκευής

Συνήθως η συσκευή SPI σκλάβου, για τη λειτουργία της αποτελείται από καταχωρητές που ο καθένας είναι υπεύθυνος για μια λειτουργία και κάθε τέτοιος καταχωρητής έχει την δική του διεύθυνση, με την οποία προσπελαύνεται καθώς και τα δικά του δεδομένα που περικλείει. Κατά την SPI επικοινωνία, ο αφέντης στέλνει την διεύθυνση του καταχωρητή του SPI σκλάβου που θέλει να επικοινωνήσει και μετά ακολουθούν τα δεδομένα που στέλνει ο αφέντης για εγγραφή στον καταχωρητή του σκλάβου ή ο σκλάβος απαντά με τα δεδομένα του καταχωρητή που ο αφέντης θέλει να διαβάσει.

Κατά την single-byte επικοινωνία προσπελαύνεται ένας καταχωρητής με μιας κάθε φορά, ενώ στην multi-byte επικοινωνία (burst mode) μεταδίδονται δεδομένα από ή προς πολλαπλούς καταχωρητές του SPI σκλάβου κάθε φορά. Περισσότερες πληροφορίες για την ανταλλαγή δεδομένων κατά τον sigle-byte ή multi-byte τρόπο επικοινωνίας με συγκεκριμένο SPI σκλάβο θα βρείτε στο datasheet της σκλάβου συσκευής.

SPI επικοινωνία στην πλατφόρμα Arduino

Οι πλακέτες Arduino όπως το Arduino Uno υποστηρίζουν SPI επικοινωνία. Οι SPI ακροδέκτες που μπορούν να χρησιμοποιηθούν είναι είτε ενσωματωμένοι στους ακροδέκτες στις ψηφιακές εισόδους και εξόδου είτε σε ξεχωριστούς ακροδέκτες πάνω στο PCB του Arduino. Ανάτρεξε στο εγχειρίδιο του Arduino για να μάθεις πως είναι ενσωματωμένοι οι SPI ακροδέκτες στις ψηφιακές πόρτες εισόδου – εξόδου του Arduino. Με το λογισμικό που είναι διαθέσιμο στο διαδίκτυο το Arduino μπορεί να διαμορφωθεί μόνο ως αφέντης.

Τώρα θα σας δείξω πως υλοποιείται η SPI επικοινωνία σε ένα sketch. Πρώτα ενσωματώνουμε την SPI βιβλιοθήκη στην αρχή του sketch, με την γραμμή κώδικα:

#include “SPI.h”

Έπειτα θα πρέπει να διαλέξουμε ένα ακροδέκτη για SS και να τον θέσουμε ως έξοδο μέσα στην συνάρτηση setup. Για παράδειγμα, χρησιμοποιούμε τον ακροδέκτη D10 για αυτό το σκοπό, τον θέτουμε ως έξοδο και του δίνουμε τιμή 1, διότι οι περισσότερες συσκευές σκλάβοι έχουν “active low” τον ακροδέκτη SS.

pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

Για να ενεργοποιήσετε την SPI επικοινωνία, προσθέστε την ακόλουθη γραμμή κώδικα στη συνάρτηση setup

SPI.begin();

Για να απενεργοποιήσετε την SPI επικοινωνία και να επανέλθουν οι ακροδέκτες στην κανονική κατάσταση, χρησιμοποιήσετε την ακόλουθη γραμμή κώδικα:

SPI.end();

Μετά θα χρειαστεί να πούμε στο Arduino με πια σειρά θα μεταδίδονται τα δεδομένα: πρώτο το MSB (το περισσότερο σημαντικό ψηφίο) ή το LSB (το λιγότερο σημαντικό ψηφίο) και θα το κάνουμε με την ακόλουθη γραμμή κώδικα:

SPI.setBitOrder(order);

όπου εδώ order είναι η ετικέτα MSBFIRST ή LSBFIRST. Μπορείς να ορίσεις την ταχύτητα με την οποία το Arduino θα στείλει τα δεδομένα. Μπορείς να χρησιμοποιήσεις την επόμενη γραμμή κώδικα ή να την παραλείψεις αν θέλεις να χρησιμοποιήσεις την προκαθορισμένη τιμή, δηλαδή την συχνότητα λειτουργίας 16ΜHz.

SPI.setClockDivider(param);

όπου param η ετικέτα π.χ. SPI_CLOCK_DIV2 αν θέλεις να χρησιμοποιήσεις συχνότητα 8MHz (τη μισή ταχύτητα ρολογιού) ή SPI_CLOCK_DIV4 για ταχύτητα 4MHz. Η ετικέτα υποστηρίζει τιμές 2, 4, 8, 16, 32, 64, 128.

Μπορείς να ορίσεις το clock polarity και clock phase που χρησιμοποιεί η SPI επικοινωνία, όπου μπορείς να διαλέξεις μια από τις τέσσερις καταστάσεις, με την ακόλουθη γραμμή κώδικα:

SPI.setDataMode(param);

ή να την παραλείψεις υπονοώντας την προκαθορισμένη. Στην param μπορείς να χρησιμοποιήσεις μια από τις ετικέτες: SPI_MODE0 (Δηλαδή: CPOL=0, CPHA=0) ή SPI_MODE1 (Δηλαδή: CPOL=0, CPHA=1) ή SPI_MODE2 (Δηλαδή: CPOL=1, CPHA=0) ή SPI_MODE3 (δηλαδή: CPOL=1, CPHA=1). Σημείωση: όλες οι SPI συσκευές θα πρέπει να λειτουργού στην ίδια διαμόρφωση.

Για αποστολή δεδομένων σε μια SPI σκλάβο συσκευή, θα πρέπει να θέσεις τον ακροδέκτη SS σε κατάσταση low για να ειδοποιηθεί ότι το Arduino (αφέντης) θέλει να επικοινωνήσει μαζί του. Μετά στέλνουμε το byte δεδομένων στον SPI σκλάβο με την ακόλουθη εντολή:

SPI.transfer(byte);

Για να λάβομε το byte δεδομένων (byte_slave) που ήδη έχει βάλει ο σκλάβος στον καταχωρητή ολίσθησης του και ταυτόχρονα την αποστολή δεδομένων από τον αφέντη, χρησιμοποιούμε την ακόλουθη γραμμή κώδικα

byte_slave = SPI.transfer(byte_master);

Μετά που έχει τελειώσει η επικοινωνία με τη συσκευή, θέτουμε τον ακροδέκτη SS σε κατάσταση high, για να πούμε ότι το Arduino έχει τελειώσει με την επικοινωνία μαζί του.

Μπορείς να χρησιμοποιήσεις πολλαπλούς SPI σκλάβους σε μια μονάδα Arduino. Συνδέεις όλους τους ακροδέκτες με το ίδιο όνομα μαζί, εκτός από τους ακροδέκτες SS. Κάθε ένας ακροδέκτης SS μιας συσκευής σκλάβου συνδέεται σε ξεχωριστό ακροδέκτη στο Arduino. Για παράδειγμα, αν θέλεις να χρησιμοποιήσεις δυο σκλάβους συσκευές σε ένα Arduino Uno (αφέντης) χρησιμοποίησε την ακόλουθη συνδεσμολογία:

Για να επικοινωνήσει το Arduino Uno με ένα συγκεκριμένο σκλάβο, πρώτα ενεργοποίησε τον σκλάβο με το κατάλληλο σήμα (low) στον ακροδέκτη SS που συνδέεται στον επιθυμητό σκλάβο.