magistrala Inter-Integrated Circuit (I2C) este un mecanism de comunicații seriale la nivel de cip care funcționează pe doar două fire. Unii dezvoltatori pronunță numele autobuzului eye-two-see, alții eye-squared-see, dar ambele se referă la același lucru. Conceput de Philips la începutul anilor 1980, I2C a fost stabilit pentru a standardiza comunicațiile între cipurile companiei, dar de atunci a devenit un standard de facto susținut de multe dispozitive de microcontroler de la plăcile Arduino la Raspberry Pi și, desigur, imps.,
magistrala fizică
I2C în sine cuprinde două fire. O linie I2C transmite date, cealaltă semnale de ceas care sincronizează conversația între dispozitive. Linia de date se numește „SDA”, linia de ceas „SCL”.în mod obișnuit, atât SDA, cât și SCL sunt conectate fiecare la o linie de alimentare de 3,3 sau 5v printr-un singur rezistor „pull-up”, câte unul pe fiecare linie. Acest lucru este necesar deoarece conexiunile SDA și SCL ale dispozitivelor sunt linii „open drain”: pot forța tensiunea pe linie la 0V sau „low”, dar nu o pot ridica la 3.3 V sau „high”., Înaltă și joasă sunt reprezentările electrice ale 1s și 0s care sunt componentele fundamentale ale informațiilor digitale. Adăugarea acestor două rezistențe — iar magistrala are nevoie doar de două, indiferent de câte dispozitive sunt conectate la ea — asigură că tensiunea crește înapoi la 3, 3 V fără scurtcircuit.I2C insistă că dispozitivele au linii de scurgere deschise pentru a se asigura că curenții mari care dăunează componentelor nu pot curge atunci când două dispozitive încearcă să semnaleze simultan.în cele mai multe cazuri, va fi de așteptat să adăugați aceste rezistențe le, dar unele dispozitive, de obicei, cele care funcționează la 3.,3V, includeți-le pentru a fi compatibile cu dispozitivele care furnizează 5V. amintiți-vă, aveți nevoie doar de o pereche de rezistențe de tracțiune pe magistrală, deci poate fi necesar să îndepărtați rezistențele de tracțiune atașate la alte dispozitive din magistrală. Deși imp are rezistențe interne de tragere proprii, acestea sunt prea slabe pentru a fi utile pentru I2C și astfel sunt dezactivate automat atunci când pinii săi sunt setați să gestioneze semnalele I2C.
Controlere și periferice
magistrala I2C separă dispozitivele în „controlere” și „periferice”., Un singur dispozitiv poate trimite impulsuri de sincronizare pe linia SCL la un moment dat, iar acesta este cel ales pentru a fi controlerul. Toate celelalte își sincronizează temporizările cu controlerul și sunt astfel considerate periferice. Controlerul-de obicei imp-și perifericele sale pot transmite și primi date, dar numai controlerul poate spune unui periferic când să transmită date înapoi.pentru ca un dispozitiv I2C să comunice cu altul în mod individual, ambele dispozitive trebuie să fie identificabile în mod unic. Această identitate este adresa I2C a dispozitivului., Adresele I2C sunt de obicei numere pe 7 biți, astfel încât un autobuz poate cuprinde până la 127 de dispozitive în total. Un octet cuprinde opt biți; bitul suplimentar este utilizat pentru a indica dacă semnalul este trimis de către controler la periferic — o „scriere” — sau în cealaltă direcție — o „citire”. Acest al optulea bit este de fapt bit zero în octetul de adresă trimis în autobuz. Adresa pe 7 biți este plasată în biți de la unu la șapte din octetul de adresă.
în conformitate cu acest format, API imp ia o adrese I2C ca o valoare de 8 biți., Furnizorii de dispozitive oferă de obicei adresele produselor lor ca un număr de 7 biți, deci este necesar să convertiți adresa de la șapte biți la opt. Acest lucru este realizat cu operatorul <<
al veveriței, care mută valorile individuale ale unui număr spre stânga. Acest proces este echivalentul înmulțirii cu două. În cod, acest proces arată astfel:
local sevenBitAddress = 0x39;local eightBitAddress = sevenBitAddress << 1;
veveriță setează automat bit zero la valoarea corectă definită I2C: 0 pentru o operație de scriere, 1 pentru o citire., Acum sunteți gata să utilizați una dintre imp e i2c metode pentru a scrie date la autobuz:
i2c.write(eightBitAddress, dataInStringForm);
7-bit adresa de dispozitivul la care doriți imp pentru a comunica cu vor fi furnizate de către componenta de producătorul și listat pe dispozitiv datasheet. Este posibil să nu fie fixat, dar selectat dintr-o gamă de adrese în funcție de tensiunea aplicată altui dintre pinii dispozitivelor., De exemplu, un TAOS TSL2561 senzor de lumină are trei adrese posibile: 0x29
, 0x49
sau 0x39
, în funcție de dacă ADR pin-ul este fixat la 0V, 3.3 V sau „plutitoare” între cele două. Spunem că valoarea este plutitoare, deoarece nu a fost selectată în mod activ pentru a funcționa la o anumită tensiune; ar putea fi orice de la 0 la 3.3 V inclusiv.
semnalizare
controlerul magistralei I2C utilizează adresa de 7 biți a unui periferic pentru a identifica componenta cu care dorește să vorbească., De fapt, semnalizarea este mai complexă decât atât, dar, din fericire, toate detaliile sunt gestionate de imp, astfel încât trebuie să furnizați adresa doar ca valoare pe 8 biți.
dacă scrieți la periferic, trebuie, de asemenea, să furnizați datele pentru a scrie, care adesea include valori de registru care instruiesc perifericul ce să facă cu datele. Documentația API imp se referă la aceste registre ca „sub-adrese”:
i2c.write(eightBitAddress, dataString);
write() necesită date în formă de șir. În consecință, poate fi necesar să convertiți valoarea stocată în alte tipuri de variabile în formă de șir.,
citirea informațiilor de pe un dispozitiv poate necesita o comandă pentru a spune dispozitivului ce date să preia. Spune imp pentru a citi datele de pe magistrala I2C implică, de asemenea, furnizarea de un al treilea parametru, numărul de octeți ai aștepta să primească:
i2c.read(eightBitAddress, controlDataString, numberOfBytesToRead);
în Spatele acestor operațiuni sunt I2C e semnale electrice, aplicat la linia SDA sincronizate cu calendarul impulsuri aplicate la SCL linie. Scrierea în autobuz implică un marker de pornire: scăderea SDA la 0V în timp ce SCL este de 3,3 V. schimbarea tensiunii SDA atunci când tensiunea SCL este ridicată definește markerii de pornire și oprire., Dacă tensiunea SDA nu se schimbă în timp ce SCL este mare, dispozitivele I2C știu că datele, mai degrabă decât markerii, sunt trimise.
SDA merge acum mare sau mic pentru a trimite fiecare bit al octetului de adresă: adresa dispozitivului pe 7 biți urmată de bitul de citire/scriere. Biții octetului sunt trimiși mai întâi pe bitul din stânga- „bitul cel mai semnificativ” — în primul rând, cu SDA mergând mare dacă valoarea bitului este 1 sau scăzută dacă este zero. Perifericul țintă va trage acum SDA scăzut pentru a semnala confirmarea primirii datelor și apoi va ieși opt biți de informații sau date de control, urmate de mai multe date, dacă este necesar., Există o pauză de confirmare ” ack ” cu un singur impuls pe SDA între fiecare opt biți trimiși, cronometrat la un al nouălea impuls SCL. Dacă perifericul nu confirmă primirea în acest fel, controlerul va detecta că SDA a rămas ridicat și va semnala o eroare.,
când datele curg de la periferic la controler, acesta din urmă recunoaște, de asemenea, primirea a opt biți trăgând SDA low pe al nouălea puls SCL, cu excepția cazului în care acesta este octetul final al unui lot, caz în care controlerul nu trage SDA low — face un semnal ” nak ” sau „nicio confirmare” — pentru a anunța perifericul că a terminat.
când am terminat, SDA merge de mare ca un marker de oprire.,
La început de transmitere este indicat de SDA scădere de la Înaltă la Joasă tensiune (dreptunghiul din stânga),
trec inversă (dreptul de dreptunghi). SCL trebuie să fie mare atunci când acest lucru are loc
Timing
viteza standard de ceas pentru comunicațiile I2C este 100kHz — 100.000 impulsuri SCL pe secundă. Este posibil să mergeți mai repede, până la 400kHz. Este posibil ca unele dispozitive să nu poată suporta această viteză; verificați fișa tehnică care însoțește dispozitivul pe care doriți să îl conectați la imp., Cu toate acestea, multe dispozitive lente folosesc o tehnică numită „întindere de ceas” pentru a forța dispozitivele mai rapide să funcționeze la viteza lor. Imp acceptă dispozitive care utilizează această tehnică. În esență, ei dețin SCL scăzut în timp ce acestea sunt preluarea datelor pe care doriți să le trimită la imp. Imp detectează acest lucru, eliberează linia SCL și așteaptă până când SCL se ridică din nou înainte de a continua.cu toate acestea, poate fi necesar să reduceți singur viteza I2C dacă caracteristicile electrice ale configurației dvs. încetinesc viteza de tranziție între 0V și 3.3 V, numită „timp de creștere”., Acest lucru este adesea cauzat de fire lungi, care măresc capacitatea circuitului. Pentru ca dispozitivele să detecteze cu succes transmisia fiecărui bit, magistrala trebuie să funcționeze mai lent. Corupția datelor sau rezultatele neașteptate sunt indicii pe care ar trebui să le căutați. Reduceți viteza magistralei I2C până când datele sunt citite cu succes.
API-ul imp oferă în prezent patru valori de ceas predefinite: 10, 50 100 și 400khz., Acestea sunt selectate prin trecerea constantă de la I2C de configurare metoda ca parametru:
i2c.configure(speedConstant);
în cazul în care valoarea de speedConstant este unul dintre
- CLOCK_SPEED_10_KHZ
- CLOCK_SPEED_50_KHz
- CLOCK_SPEED_100_KHZ
- CLOCK_SPEED_400_KHZ
configurarea Unui imp Pentru I2C
I2c obiect în exemplul de linii de cod prezentate mai sus nu este furnizat direct de către pmi, dar alese de tine în funcție de datele alese de imp e ace veți fi, folosind pentru comunicare I2C., Fiecare tip de imp are mai multe autobuze I2C, toate puse la dispoziție la pornire. Consultați pinul MUX pentru tipul de imp pe care îl utilizați pentru a vedea ce obiecte I2C vă sunt disponibile. Aici, vom presupune că utilizați un imp001. La imp001 două I2C autobuze sunt pe pinii 1 și 2, și pinii 8 și 9, respectiv instanced ca proprietăți i2c12 și i2c89 de hardware obiect atunci când imp pornește. Pinii 1 și 8 sunt atribuite SCL, 2 și 9 la SDA.,
Acesta este un lucru obișnuit pentru a face referire la alegerea ta cu o variabilă globală:
i2c <- hardware.i2c12;i2c.configure(CLOCK_SPEED_100_KHZ);
Exemplu de Cod
codul De mai jos funcționează cu TAOS TSL2561 vizibil și infraroșu senzor de lumină, o 3.3 V dispozitiv care utilizează I2C pentru a comunica cu gazda microcontroler. Fișa tehnică a cipului poate fi descărcată de pe site-ul Adafruit. Adafruit vinde cip pe o placă breakout low-cost, care include rezistențe adecvate pull-up pe pinul de alimentare, VCC. Aceasta înseamnă că este gata să se conecteze direct la pinii I2C ai unui imp.,
Adafruit e TSL2561 breakout bord
Notă După acest articol a fost scris, Adafruit actualizat TSL2561 senzor de bord. Noua versiune Funcționează cu codul curent.
Iată codul, pentru agent și apoi dispozitivul:
ce face codul
codul agentului răspunde la o solicitare HTTP primită prin notificarea dispozitivului că necesită o citire. Pentru simplitate, citirea este pur și simplu afișată în jurnal.codul dispozitivului citește senzorul și calculează o valoare lux în funcție de matematica stabilită în fișa tehnică TSL2561., Prima parte a programului stabilește constante pentru registrele și setările cheie ale TSL2561, inclusiv opțiunile de adresă I2C. Alte constante sunt utilizate în procesul de conversie a luminozității.
Cabluri de până la imp
În program punctul de pornire, codul pseudonime unul din imp e I2C pin configurat ca o variabilă globală, configurează bus-ul la 100 khz și apoi se mută TSL2561 e adresa I2C un pic spre stânga, deci este gata pentru a fi utilizate cu imp I2C funcții. Apoi setează senzorul., Doar pentru a verifica acest lucru a funcționat, citim registrul de control: valoarea returnată ar trebui să fie 3 Dacă TSL2561 tocmai a pornit sau 51 dacă dispozitivul a fost deja pornit.
apoi, codul stabilește rezoluția ADC a senzorului prin registrul de sincronizare TSL2561, apoi stabilește câștigul de semnal la mare.
în cele din urmă, îi spunem imp cum să răspundă la notificările "sense"
de la agent. Aceasta solicită o funcție care citește cei doi senzori de lumină ai TSL2561, valori digitale pentru care sunt stocate în cele patru registre ADC pe 8 biți ale cipului., Primele două dau o citire optică combinată pe 16 biți și infraroșu, a doua pereche o valoare IR numai pe 16 biți. Funcțiile readSensorAdc0() și readSensorAdc1() converti individuale înregistra valori în 16-bit numere prin înmulțirea cel mai semnificativ octet cu 256 și adăugarea de valoare de la cel mai puțin semnificativ octet. Multiplicarea este realizată prin schimbarea de opt biți numărul de biți la stânga opt locuri cu Veverita << operator.,
codul furnizează apoi ambele citiri unei a treia funcții pentru a calcula o luminozitate finală, valoarea „lux”.
Lectură suplimentară
- erori I2C-cum să depanați problemele de citire și scriere I2C