Serial Peripheral Interface (SPI) utvecklades av Motorola för att tillåta sina marker att kommunicera med varandra, mycket som Philips utarbetade I2C seriell buss för sina egna integrerade kretsar. Medan dessa två bussar gör i stort sett samma jobb, båda har blivit nästan lika vanligt, och många kringutrustning använder antingen den ena eller den andra för att kommunicera med en värdmikrokontroller. Denna allestädes närvarande är varför imps stöder dem båda.
SPI har vissa fördelar jämfört med I2C, särskilt stöd för högre dataöverföringshastighet., SPI har också en duplex kapacitet som gör den särskilt lämplig för de program som kräver samtidig tvåvägskommunikation.
å andra sidan kräver SPI minst tre ledningar, delade av alla enheter på bussen och ett antal enhetsvalslinjer, en för varje kringutrustning som är ansluten till styrenheten. I2C kräver däremot bara två ledningar; Den använder unika adresser för att identifiera alla enheter på bussen., Detta gör att arbeta med flera enheter enklare än SPI: s adresslösa tillvägagångssätt, även om vissa utvecklare föredrar att använda hårdvara för att välja en enhet snarare än adressdata.
styrenheter och kringutrustning
SPI separerar enheter i ”styrenheter” och ”kringutrustning”. Endast en enhet kan skicka ut tidspulser för att synkronisera dataöverföringar, och det är den som valts för att vara styrenheten. Alla andra, som synkroniserar sina tidpunkter med styrenheten, anses vara dotterbolag kringutrustning., Styrenheten-som i din produkt för närvarande måste vara dess imp-och dess kringutrustning kan alla överföra och ta emot data, men endast styrenheten kan fastställa tidsmönstret som de alla arbetar med. Denna etablering av ett fast tidsschema är det som gör SPI, som I2C, en ”synkron” buss.
den fysiska bussen
IMPS SPI-implementering har fyra linjer:
- SCLK, den seriella klocksignalen från regulatorn.
- COPI, kort för ”Controller Ut, Perifera I’ (ibland märkt MOSI i gamla datablad).,
- CIPO, kort för ”Controller in, Peripheral Out” (ibland märkt MISO).
- CS, kort för ”Chip Select” (ibland märkt SS, NSS eller SYNC)
COPI och CIPO är dataöverföringslinjerna.
imp001 och imp002 inte tillhandahålla särskilda CS pins: i stället kan du använda någon av dessa imp ’ s andra GPIO stift. Imp003 och uppåt ger dedikerade CS pins som en del av sina SPI-bussar, markerade på imp pin mux-sidan.
Observera imp005 ger en dedikerad chip select pin på var och en av sina två SPI bussar. För spiBCAD detta är pin D; för spi0 detta är pin CS0., Imp API metod chipselect () kan användas för att ta kontroll över påståendet och de-påstående av dessa chip select pins (se metoden dokumentation för mer information).
SPI på imp: upp till fyra linjer ansluter till en enda kringutrustning
detta tillvägagångssätt följer Motorolas definition av SPI: att varje busstransaktion — i huvudsak en sats databytes — ska kopplas till en specifik kringutrustning., Texas Instruments ändrade SPI-specifikationen så att varje byte kan skickas till en specifik perifer, även om detta kräver en dedikerad CS-linje. Det här läget stöds för närvarande inte av någon imp.
signalering
Om vi antar att vi har en enda kringutrustning ansluten till styrenheten, initieras kommunikation av styrenheten som drar CS-linjen låg. De berättar perifera redo att konversera. Nu börjar regulatorn skicka klockpulser ut längs SCLK-linjen; vanligtvis är dataöverföringar knappade till den stigande kanten av varje puls, men det är inte alltid fallet.,
klockad data in och Ut: imp skickar ett kommando, perifer Returnerar data
regulatorn kommer nu att överföra data på COPI-linjen, aktivt driver linjen högt för att signalera en 1 eller låg för en 0. Den perifera kommer att läsa signalen-vilket kan vara ett kommando för att en sensorläsning ska skickas, till exempel – och det kommer att returnera den informationen på CIPO-linjen, återigen driva linjen för att hålla sig hög för att signalera en 1 eller köra den låg för att överföra en 0., Detta krav på att linjen aktivt drivs högt eller lågt, snarare låta det lösa sig till ett tillstånd eller det andra genom att ansluta ett motstånd, är anledningen till att SPI kan stödja högre hastigheter än I2C kan. I2C förlorar överföringstiden medan dess pull-up motstånd returnerar linjen till hög.
som sagt är det ändå bra att också ha en pull – up på en CS-linje för att säkerställa att den går högt när imp startar eller sover och därför inte kan köra linjen högt manuellt. Att hålla linjen hög säkerställer att periferin ignorerar eventuella glitches på data-och klocklinjerna.,
När Styrenheten har vad den vill, driver den CS-linjen högt en gång till och kringutrustningen kan vila.
imp SPI-alternativ
varje imp har ett antal oberoende SPI-bussar, som nås som Egenskaper för enhetens hårdvaruobjekt, vilket instansieras vid uppstart. Varje imp: s pin mux-tabell visar att det finns många val, beroende på vilken typ av imp du använder i din produkt. Detta dokument förutsätter att du använder en imp001, så du bör konsultera pin mux tabellen om du arbetar med en annan imp., Imp001: s två SPI-bussar är både tretrådiga implementeringar av bussen och anslutna till stiften 1, 8 och 9 respektive 2, 5 respektive 7. Stift 1 och 5 är SCLK; 8 och 7 COPI; och 9 och 2 CIPÓ. Oavsett vilken av de två bussar du använder, är det bra praxis att alias det i början:
spi1 <- hardware.spi257;spi2 <- hardware.spi189;
konfigurera antingen för användning är helt enkelt en fråga om att berätta imp hur snabbt du vill att bussen ska köras, och för att ge en uppsättning konstanter som tillsammans bestämmer hur bussen ska fungera:
spi1.configure(modeFlags, speed);
först hastigheten., This is simply an integer value giving the throughput in kiloHertz (kHz):
The specific SPI data rates available (in kHz) are as follows:
imp001, imp002 | imp003 | imp004m | imp005 | imp006 | |
spi189 | spi257 | spiEBCA spiLGDK |
spiAHSR spiGJKL |
spiBCAD spi0 |
spiXTUVW |
15,000 | 30,000 | 18,000 | 24,000 | The SPI data rates available range from 5KHz to 22.,8MHz The SPI is clocked by dividing 160MHz by any integer from 7 to 32,000 inclusive |
Min. 187KHz, max. 750KHz |
7500 | 15,000 | 9000 | 12,000 | ||
3750 | 7500 | 4500 | 6000 | ||
1875 | 3750 | 2250 | 3000 | All others | |
937.50 | 1875 | 1125 | 1500 | Min. 187KHz, theoretical max. 24MHz |
|
468.75 | 937.50 | 562.50 | 750 | ||
234.,375 | 468.75 | 281.25 | 375 | ||
117.1875 | 234.375 | 140.,g) kant | |||
MSB_FIRST | Sänd mest signifikanta biten först (standard) | ||||
LSB_FIRST | Skicka den minst signifikanta biten först | ||||
NO_SCLK | SCLK pin-kod används inte | ||||
USE_CS_L | Aktivera användning av dedikerad krets välj pin-kod (imp005 bara) |
Dessa kan kombineras, om du behöver dem för att vara, med hjälp av den logiska ELLER operatör, |
, även om vissa är ömsesidigt uteslutande, så bör inte kombineras: SIMPLEX_TX och SIMPLEX_RX, till exempel., För att använda både CLOCK_IDLE_LOW och CLOCK_2ND_EDGE, till exempel, istället för att ange en enda konstant som en parameter i configure () – metoden skulle du inkludera båda, åtskilda av symbolen |
:
spi1.configure(SIMPLEX_TX | MSB_FIRST | CLOCK_IDLE_LOW, 400);
kombinationer kan vara nödvändiga om de anges av periferns datablad, även om det kanske inte är omedelbart uppenbart för nykomlingen. Datablad kan tala om en enhets ’SPI-läge’, eller dess cpol (Klockpolaritet) och CPHA (Klockfas) värden., CPOL och CPHA bestämmer vilka kanter av klocksignalen som används för att driva och sampla datasignaler. Var och en av dessa två parametrar har två möjliga tillstånd, för fyra möjliga kombinationer i alla:
SPI-lägen
SPI-lägen indexerar helt enkelt dessa kombinationer snarare än de separata cpol-och CPHA-värdena. Regulatorn och perifer måste kommunicera med samma cpol-och CPHA-värden, och därmed samma läge., Flera kringutrustning kan innebära olika konfigurationer, så styrenheten måste omkonfigurera sig varje gång den behöver kommunicera med en specifik kringutrustning.,följande tabell:
läsa och skriva Data
Efter att ha konfigurerat SPI-bussen, använd skriv () – metoden för att skicka en rad byte till den perifera enheten:
spi1.write("This is an LCD display");
användning av en sträng är valfri: Du kan också skicka en blob av raw data bytes:
local blob = blob(4); // Create a four-byte blob...blob.writen(0xDEADBEEF, 'i'); // ...and write a 32-bit value to itspi1.write(blob);
Om du vill läsa en sträng eller skriva en Blob, du behöver en av Imp API: s två SPI-Läsmetoder:
local bytes = spi1.readblob(8);local inputString = spi1.readstring(16);
heltalsvärdet som skickas som en parameter är respektive antalet byte som ska läsas in i Blob och antalet tecken som ska sättas in i strängen., Naturligtvis, eftersom ett tecken tar upp en byte, är dessa två metoder likvärdiga. Den senare omvandlar helt enkelt blob till sträng för dig.
på grund av SPI-bussens ”full duplex” natur skriver och läser du alltid samtidigt. Med läs-och skrivkommandon har vi sett hittills, data som rör sig i motsatt riktning från den vi är intresserade av ignoreras eller nollställs. Så, när du skriver en sträng, säg, ignoreras Alla data som kommer till imp från periferin., Under någon av de två läsoperationerna skrivs en matchande storlek på ”dummy” nollbytes till perifer: om du läser åtta byte, säg, skrivs åtta 0s automatiskt.
för att hantera denna samtidiga tvåvägskommunikation har imp API en fjärde metod som kombinerar läser och skriver:
local inputString = spi1.writeread(outputString);
eftersom strängutmatningen skickas ut längs COPI-linjen fylls variabeln inputString av databytes som kommer på CIPO. Du kan skicka och ta emot strängar eller blobbar, men både inmatning och utmatning måste vara av samma typ., Men stor din utgång blob, din ingång blob kommer att vara av samma storlek. På samma sätt kommer inmatnings-och utmatningssträngar att vara av samma längd.
full duplex operation kan också användas med enhet som inte förväntar sig att fungera på det sättet — de som kräver att läsa och skriva ”dummy” byte för att vara ett specifikt, icke-nollvärde. Detta krav utesluter användning av vanliga skriv (), readblob() och readstring() metoder, men writeread () kan användas i deras ställe för att se till att enhetens föredragna dummy värden används.,
exempelkod
följande kod fungerar med de analoga enheterna adxl345 digital accelerometer, en del som använder SPI för att kommunicera med sin värdmikrokontroller. Det stöder också I2C, och stiften på denna Adafruit breakout-bräda, som är baserad på chipet, är märkta i enlighet därmed. Chipets datablad kan laddas ner från webbplatsen för analoga enheter.
hur koden fungerar
vi använder en imp001 ’ s spi257-buss, med Alias nära början av noteringen som spi. Vi alias också pin 8 som CS-linjen. Funktionen spiWriteReg () visar hur dessa används., En skrivtransaktion signaleras genom att byta CS-linje låg. Nästa adressen till registret vi vill skriva till konverteras från en ekorre 32-bitars signerat heltal till ett 8-bitars värde genom att skriva det till en klump. Denna blob skrivs sedan till spi-bussen. Vi gör samma sak med det värde vi vill att ADXL345 ska sätta i det registret, och sedan ställer vi CS-linjen högt igen för att signalera transaktionens slut.,
Adafruit/Analog Devices ADXL345
funktionen spiReadReg() fungerar på samma sätt, bara den här gången läser vi värdedata från bussen efter att ha skrivit källregisterets adress. ADXL345 kräver att vissa justeringar görs till registeradressen i det här fallet: bit 7 måste ställas in för att markera transaktionen som en läsoperation och bit 6 måste ställas in för att berätta för chipet att vi förväntar oss att mer än en enda byte ska skickas tillbaka.,
där programmet korrekt startar konfigurerar vi imp: s SPI-buss för att matcha kraven i adxl345-chipet. Den använder SPI-Läge 3 — ie. både CPOL och CPHA bör ställas in så att vi motsvarar imp parameter: CLOCK_IDLE_HIGH | CLOCK_2ND_EDGE i konfigurera () – anropet. Vi ställer också in hastigheten till 100kHz. Därefter konfigureras imp: s pin 8, som fungerar här som CS-pin, som en digital utgång och ställs in högt.
koppla upp ADXL345
andra funktioner i programmet initierar ADXL345 själv snarare än SPI-bussen., ADXL345 initieras och koden läser i värdet från registeradressen 0x00
för att säkerställa att enheten finns på bussen. Chipet har ett självtestläge som gör att en serie kalibreringsavläsningar kan tas; detta gör vi och lagrar resultaten. Senare, i funktionsslingan (), används dessa värden för att justera de slutliga avläsningarna från accelerometern.,
ADXL345 sparar sina X-, y – och z-axelprover som 16-bitarsvärden, var och en i två 8-bitarsregister; loop() använder spiReadReg () – funktionen för att förvärva varje värde två komponenter och omvandlar dem sedan till enstaka värden genom att multiplicera den mest signifikanta byte med 256 och lägga till resultatet värdet av den minst signifikanta byte.