SPI
busz spi en: Serial Peripheral Interface
A Serial Peripheral Interface busz (SPI) egy szinkron soros kommunikációs interfész specifikáció, amelyet rövid távú adatátvitelre (MicroLAN) használnak, elsősorban beágyazott rendszerekben. A felületet 1980-as évek végén fejlesztette ki a Motorola és az de facto szabvánnyá vált. Tipikus SPI alkalmazások közé tartozik az SD kártyákkal és a folyadékkristályos kijelzőkkel folytatott kommunikáció.
Az SPI eszközök full-duplex módban kommunikálnak master-slave architektúrán keresztül. A hálozaton egy master tartózkodhat csak. Több slave eszköz esetén az egyes egységek a slave-select (SS) funkción keresztül érhetők el.
Néha az SPI-t négyvezetékes soros busznak is nevezik/jellemzik.
A busz sebessége az eredeti specifikáció szerint 100 kbps volt, ez emelkedett az 1998-as specifikációval 3,4 Mbps-re.
A busz maximális távolsága nagyjából 8 m.
Az SPI lehetséges portjai
- SCLK: Soros óra (master kimenet).
- MOSI: Master Output Slave Input, vagy Master Out Slave In
- MISO: Master Input Slave kimenet, vagy Master In Slave Out
- SDIO: Soros adat I/O (kétirányú I / O)
- SS: Slave Select (master kimenet)
SPI hálózatkonfiguráció
Az SPI hálózat alapvelően két struktúra szerint épülhet fel:
Független slave konfiguráció
Ebben a struktúrában a master-nek annyi kiválasztó SS porttal kell rendelkeznie, ahány slave található a hálózatban. Ezek közül mindig csak a kiválasztott slave-vel folytat kétirányú kommunikációt. Mivel a slave-ek MISO kimenetei össze vanna kötve, azoknak három áramszinttel kell rendelkezniük: alacsony, magas, magas impedancia.
Daisy chain konfiguráció
Ebben az esetben a master által kiadott MOSI jelsor először az első slave MOSI-jára kerül, majd onnan a MISO kimeneten keresztül jut el a következő slave MOSI-jára, és így tovább.
Az SPI kommunikáció
Az SPI-ben mindig a master kezdeményezi a kommunikációt azzal, hogy a kiválasztott slave felé az SS jel állapotát magasról alacsonyra váltja. Ez után a master által kiadott órajellel a forgalmazás mindkét csatornán egyidejűleg történik, az adatátvitelre alkalmazott regiszterek szinkronban kerülnek feltöltésre, általában a legmagasabb helyiértékekkel kezdve.
A regiszterek feltötése után azokat tárolja mindkét egység, és ismétli a regisztertöltést az átvitel végéig. A regiszterek leggyakrabban 8 bitesek, de előfordulhat 16 / 12 bites változatuk is.
Az átvitel végeztével a master leállítja az SLCK órajelet és az SS kiválasztót ismét magas állapotba teszi.
Óra polaritás
Az órajel kezdő polaritása (CPOL) lehet felfutóél vezérelt (CPHA=0) és lefutóél vezérelt (CPHA=1) is, úgy, mint ahogy ez a lenti képen követhető:
Mód
Az SPI-ben négy kommunikációs mód áll rendelkezésre (MODE 0, 1, 2, 3), melyek alapvetően az SCLK élfigyelését határozzák meg:
SPI / Arduino
spi.h
#ifndef _SPI_H_ #define _SPI_H_ #include <avr/io.h> extern void spi_init(); extern void spi_transfer_sync (uint8_t * dataout, uint8_t * datain, uint8_t len); extern void spi_transmit_sync (uint8_t * dataout, uint8_t len); extern uint8_t spi_fast_shift (uint8_t data);
spi.c
#include "spi.h" #include <avr/io.h> #include <avr/interrupt.h> #define PORT_SPI PORTB #define DDR_SPI DDRB #define DD_MISO DDB4 #define DD_MOSI DDB3 #define DD_SS DDB2 #define DD_SCK DDB5 void spi_init() // Initialize pins for spi communication { DDR_SPI &= ~((1<<DD_MOSI)|(1<<DD_MISO)|(1<<DD_SS)|(1<<DD_SCK)); // Define the following pins as output DDR_SPI |= ((1<<DD_MOSI)|(1<<DD_SS)|(1<<DD_SCK)); SPCR = ((1<<SPE)| // SPI Enable (0<<SPIE)| // SPI Interrupt Enable (0<<DORD)| // Data Order (0:MSB first / 1:LSB first) (1<<MSTR)| // Master/Slave select (0<<SPR1)|(1<<SPR0)| // SPI Clock Rate (0<<CPOL)| // Clock Polarity (0:SCK low / 1:SCK hi when idle) (0<<CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling) SPSR = (1<<SPI2X); // Double Clock Rate } void spi_transfer_sync (uint8_t * dataout, uint8_t * datain, uint8_t len) // Shift full array through target device { uint8_t i; for (i = 0; i < len; i++) { SPDR = dataout[i]; while((SPSR & (1<<SPIF))==0); datain[i] = SPDR; } } void spi_transmit_sync (uint8_t * dataout, uint8_t len) // Shift full array to target device without receiving any byte { uint8_t i; for (i = 0; i < len; i++) { SPDR = dataout[i]; while((SPSR & (1<<SPIF))==0); } } uint8_t spi_fast_shift (uint8_t data) // Clocks only one byte to target device and returns the received one { SPDR = data; while((SPSR & (1<<SPIF))==0); return SPDR; }