De Serial Peripheral Interface (SPI) is ontwikkeld door Motorola om zijn chips met elkaar te laten communiceren, net zoals Philips de I2C serial bus voor zijn eigen geïntegreerde schakelingen ontwikkelde. Hoewel deze twee bussen grotendeels hetzelfde werk doen, zijn beide bijna even alledaags geworden, en veel randapparatuur gebruikt de een of de ander om te communiceren met een host microcontroller. Deze alomtegenwoordigheid is de reden waarom de GMP ‘ s beide ondersteunen.
SPI heeft enkele voordelen ten opzichte van I2C, in het bijzonder ondersteuning voor hogere gegevensoverdrachtssnelheid., SPI heeft ook een duplex-mogelijkheid waardoor het bijzonder geschikt is voor toepassingen die gelijktijdige tweewegcommunicatie vereisen.
aan de andere kant, SPI vereist ten minste drie draden, gedeeld door alle apparaten op de bus, en een aantal apparaat-selectielijnen, een voor elk randapparaat aangesloten op de controller apparaat. I2C, daarentegen, vereist slechts twee draden; het gebruikt unieke adressen om alle apparaten op de bus te identificeren., Dit maakt het werken met meerdere apparaten eenvoudiger dan SPI ‘ s adresloze aanpak, hoewel sommige ontwikkelaars liever hardware gebruiken om een apparaat te selecteren in plaats van adresgegevens.
Controllers en randapparatuur
SPI scheidt apparaten in “controllers” en “randapparatuur”. Slechts één apparaat kan timing pulsen verzenden om gegevensoverdracht te synchroniseren, en dat is degene die gekozen is om de controller te zijn. Alle andere, die hun timings synchroniseren met de controller, worden beschouwd als secundaire randapparatuur., De controller – die in uw product op dit moment zijn imp moet zijn — en zijn randapparatuur kunnen allemaal gegevens verzenden en ontvangen, maar alleen de controller kan het tijdpatroon vaststellen waarop ze allemaal werken. Deze vaststelling van een vaste timing schema is wat SPI, net als I2C, een ‘synchrone’ bus maakt.
de fysieke Bus
de SPI-implementatie van het imp heeft vier regels:
- SCLK, het seriële kloksignaal van de controller.
- COPI, kort voor ‘Controller Out, Peripheral In’ (soms gelabeld MOSI in oude datasheets).,
- CIPO, afkorting voor ‘Controller In, Peripheral Out’ (soms MISO genoemd).
- CS, kort voor ‘Chip Select’ (soms aangeduid als SS, nSS of SYNC)
COPI en CIPO zijn de gegevensoverdrachtlijnen.
De imp001 en imp002 bieden geen speciale CS-pinnen: in plaats daarvan kunt u elk van deze imp ‘ s andere GPIO-pinnen gebruiken. De imp003 en up bieden speciale CS-pinnen als onderdeel van hun SPI-bussen, gemarkeerd op de imp pin mux-pagina.
Opmerking De imp005 biedt een speciale chip select-pin op elk van de twee SPI-bussen. Voor spiBCAD is dit pin D; voor spi0 is dit pin CS0., De imp API method chipselect () kan worden gebruikt om controle over de assertion en de-assertion van deze chip select pins (zie de methode documentatie voor meer informatie).
SPI op het imp: maximaal vier regels verbinden met een enkel randapparaat
Deze aanpak volgt Motorola ‘ s definitie van SPI: dat elke bustransactie — in wezen een batch data bytes — moet worden gekoppeld aan een specifiek randapparaat., Texas Instruments wijzigde de SPI-specificatie zodat elke byte naar een specifieke rand kan worden verzonden, hoewel hiervoor een speciale CS-lijn nodig is. Deze modus wordt momenteel door geen enkele imp ondersteund.
signalering
aangenomen dat er één randapparaat is aangesloten op de controller, wordt de communicatie geïnitieerd door de controller die de CS-lijn laag trekt. Het vertelt de periferie om zich klaar te maken om te converseren. Nu begint de controller klokpulsen langs de sclk-lijn te verzenden; meestal worden gegevensoverdracht gekoppeld aan de stijgende rand van elke puls, hoewel dat niet altijd het geval is.,
het in-en uitschakelen van de gegevens: De imp stuurt een commando, de periferie geeft gegevens terug
de controller zal nu gegevens verzenden op de COPI-lijn, waarbij de lijn actief wordt gedreven om een 1 of een laag voor een 0 aan te geven. De randapparatuur zal het signaal lezen — wat bijvoorbeeld een opdracht kan zijn voor het verzenden van een sensorlezing — en het zal die informatie op de CIPO-lijn retourneren, waarbij de lijn opnieuw wordt aangedreven om hoog te blijven om een 1 te signaleren of om het laag te drijven om een 0 te verzenden., Deze eis dat de lijn actief hoog of laag wordt gedreven, in plaats van het te laten settelen aan de ene of de andere staat door het aansluiten van een weerstand, is de reden dat SPI hogere snelheden kan ondersteunen dan I2C kan. I2C verliest transmissietijd terwijl de pull-up weerstand de lijn naar hoog terugbrengt.
Dat gezegd hebbende, is het toch een goede gewoonte om ook een pull-up op een CS-lijn te hebben om ervoor te zorgen dat deze hoog gaat wanneer de imp opstart of slaapt en daarom niet in staat is om de lijn handmatig hoog aan te drijven. Het houden van de lijn hoog zorgt ervoor dat de rand zal negeren eventuele glitches op de data en klok lijnen.,
wanneer de controller heeft wat hij wil, drijft hij de CS-lijn weer hoog aan en kan de randapparatuur rusten.
imp SPI-opties
elke imp heeft een aantal onafhankelijke SPI-bussen, toegankelijk als eigenschappen van het hardware-object van het apparaat, dat wordt geïnstalleerd bij het opstarten. Elke imp ‘ s pin mux tabel laat zien dat er veel keuzes, afhankelijk van welk type imp u gebruikt in uw product. Dit document gaat ervan uit dat u een imp001 gebruikt, dus u moet de pin MUX tabel raadplegen als u met een andere imp werkt., De twee SPI-bussen van de imp001 zijn beide driedraads implementaties van de bus, en aangesloten op pinnen 1, 8 en 9, en 2, 5 en 7, respectievelijk. Pinnen 1 en 5 zijn SCLK; 8 en 7 COPI; en 9 en 2 CIPO. Welke van de twee bussen u ook gebruikt, het is een goede gewoonte om het vanaf het begin te alias:
spi1 <- hardware.spi257;spi2 <- hardware.spi189;
Het instellen van een van beide voor gebruik is gewoon een kwestie van het vertellen van de imp hoe snel u wilt dat de bus rijdt, en om een set constanten te leveren die samen bepalen hoe de bus zal werken:
spi1.configure(modeFlags, speed);
eerst de snelheid., 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) rand | |||
MSB_FIRST | Stuur meest significante bit van de eerste (standaard) | ||||
LSB_FIRST | het Verzenden van de minst significante bits eerste | ||||
NO_SCLK | SCLK pin niet gebruikt worden | ||||
USE_CS_L | schakelt u het gebruik van de speciale chip select pin (imp005 alleen) |
Deze kunnen worden gecombineerd, als je ze nodig hebt om, met behulp van de logische operator OF |
, maar sommige zijn wederzijds exclusief en mag dus niet worden gecombineerd: SIMPLEX_TX en SIMPLEX_RX, bijvoorbeeld., Om zowel CLOCK_IDLE_LOW als CLOCK_2ND_EDGE te gebruiken, bijvoorbeeld, in plaats van het invoeren van een enkele constante als parameter in de configure() methode, zou je beide opnemen, gescheiden door de |
symbool:
spi1.configure(SIMPLEX_TX | MSB_FIRST | CLOCK_IDLE_LOW, 400);
combinaties kunnen nodig zijn als ze worden gespecificeerd door het gegevensblad van het randapparaat, hoewel dit niet direct duidelijk is voor de nieuwkomer. Datasheets kunnen praten over de ‘SPI Mode’ van een apparaat, of de CPOL (Klokpolariteit) en CPHA (Klokfase) waarden., CPOL en CPHA bepalen welke randen van het kloksignaal worden gebruikt om datasignalen aan te drijven en te bemonsteren. Elk van deze twee parameters heeft twee mogelijke toestanden, voor vier mogelijke combinaties in alle:
SPI modi
SPI modi indexeer gewoon die combinaties in plaats van de afzonderlijke CPOL en CPHA waarden. De controller en de randapparatuur moeten communiceren met behulp van dezelfde CPOL en CPHA waarden, en dus dezelfde modus., Meerdere randapparatuur kan verschillende configuraties betekenen, dus de controller moet zichzelf opnieuw configureren elke keer dat hij moet communiceren met een specifieke randapparatuur.,in de volgende tabel:
het Lezen En Schrijven van Gegevens
Na het configureren van de SPI-bus, gebruikt u de write() methode voor het verzenden van een reeks van bytes naar het randapparaat:
spi1.write("This is an LCD display");
het Gebruik van een string is optioneel: u kunt ook een blob van ruwe 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);
Of u nu wilt lezen, een string of een blob, moet u een van de imp-API ‘ s twee SPI lezen methoden:
local bytes = spi1.readblob(8);local inputString = spi1.readstring(16);
De integer waarde wordt doorgegeven als een parameter is, respectievelijk het aantal te lezen bytes in de blob en het aantal karakters in de string., Natuurlijk, omdat één karakter één byte in beslag neemt, zijn deze twee methoden gelijkwaardig. De laatste zet gewoon blob naar string voor u.
vanwege de’ full duplex ‘ aard van de SPI bus, schrijven en lezen altijd gelijktijdig plaatsvinden. Met de lees-en schrijfopdrachten die we tot nu toe hebben gezien, worden gegevens die in de tegenovergestelde richting bewegen van degene waarin we geïnteresseerd zijn genegeerd of op nul gezet. Dus, als je een string schrijft, laten we zeggen, alle gegevens die aankomen bij de imp van de randapparatuur worden genegeerd., Tijdens een van de twee leesbewerkingen wordt een overeenkomstige grootte van ‘dummy’ nul bytes naar de randapparatuur geschreven: als je acht bytes leest, bijvoorbeeld, worden acht 0s automatisch geschreven.
om deze gelijktijdige tweerichtingscommunicatie te beheren, heeft de imp API een vierde methode die leest en schrijft combineert:
local inputString = spi1.writeread(outputString);
. U kunt strings of blobs verzenden en ontvangen, maar zowel input als output moeten van hetzelfde type zijn., Hoe groot uw output blob ook is, uw input blob zal van dezelfde grootte zijn. Ook zullen invoer-en uitvoerreeksen van dezelfde lengte zijn.
Full-duplex-operatie kan ook worden gebruikt met een apparaat dat niet verwacht op die manier te werken — die waarvoor de lees-en schrijfbytes van de ‘dummy’ een specifieke, niet-nulwaarde moeten zijn. Deze eis sluit het gebruik van de reguliere write(), readblob() en readstring() methoden uit, maar writeread() kan in hun plaats worden gebruikt om ervoor te zorgen dat de voorkeur dummy waarden van het apparaat worden gebruikt.,
voorbeeld Code
de volgende code werkt met de analoge apparaten ADXL345 digital accelerometer, een deel dat SPI gebruikt om te communiceren met zijn Host microcontroller. Het ondersteunt ook I2C, en de pinnen op deze Adafruit breakout board, die is gebaseerd op de chip, zijn dienovereenkomstig geëtiketteerd. De datasheet van de chip kan worden gedownload van de website van analoge apparaten.
hoe de Code werkt
we gebruiken de spi257-bus van imp001, alias aan het begin van de lijst als spi. We alias ook speld 8 als de CS-lijn. De functie spiWriteReg () laat zien hoe deze worden gebruikt., Een schrijftransactie wordt gesignaleerd door de CS-lijn laag te schakelen. Vervolgens wordt het adres van het register waar we naar willen schrijven geconverteerd van een eekhoorn 32-bit integer naar een 8-bit waarde door het naar een blob te schrijven. Deze blob wordt dan naar de SPI bus geschreven. We doen hetzelfde met de waarde die we willen dat de ADXL345 in dat register wordt gezet, en dan zetten we de CS-lijn weer hoog om het einde van de transactie aan te geven.,
de Adafruit/Analog Devices ADXL345
de functie spiReadReg() werkt op dezelfde manier, alleen dit keer lezen we waardegegevens van de bus na het schrijven van het adres van het bronregister. ADXL345 vereist in dit geval enkele aanpassingen aan het registeradres: bit 7 moet worden geplaatst om de transactie als gelezen verrichting te markeren, en bit 6 moet worden geplaatst om de spaander te vertellen dat wij meer dan één enkele byte verwachten terug te worden gestuurd.,
waar het programma juist start, configureren we de SPI bus van de imp om aan de vereisten van de ADXL345 chip te voldoen. Het maakt gebruik van SPI Mode 3-ie. zowel CPOL als CPHA moeten worden ingesteld-dus we gebruiken de equivalente Imp parameter: CLOCK_IDLE_HIGH / CLOCK_2ND_EDGE in de configure() aanroep. We hebben ook de snelheid ingesteld op 100kHz. Vervolgens wordt de pin 8 van de imp, die hier werkt als de CS-pin, geconfigureerd als een digitale uitgang en hoog ingesteld.
bedrading van de ADXL345
andere functies in het programma initialiseren de ADXL345 zelf in plaats van de SPI bus., De ADXL345 wordt geïnitialiseerd, en de code leest de waarde van registeradres 0x00
om ervoor te zorgen dat het apparaat aanwezig is op de bus. De chip heeft een zelftestmodus waarmee een reeks kalibratiemetingen kan worden uitgevoerd; dit doen we en slaan de resultaten op. Later, in de function loop (), worden deze waarden gebruikt om de eindwaarden van de versnellingsmeter aan te passen.,
De ADXL345 slaat zijn X-, y – en z-as samples op als 16-bits waarden, elk in twee 8-bits registers; loop() gebruikt de spiReadReg () functie om de twee componenten van elke waarde te verkrijgen en zet ze vervolgens om in enkele waarden door de meest significante byte te vermenigvuldigen met 256 en aan het resultaat de waarde van de minst significante byte toe te voegen.