inter-Integrated Circuit (I2C) bus är en seriell kommunikationsmekanism på chip-nivå som fungerar över bara två ledningar. Vissa utvecklare uttalar bussens namn eye-two-see, andra eye-squared-see, men båda hänvisar till samma sak. Designad av Philips i början av 1980-talet, I2C etablerades för att standardisera kommunikationen mellan företagets chips, men det har sedan dess blivit en de facto-standard som stöds av många mikrokontroller enheter från Arduino styrelser till Raspberry Pi och, naturligtvis, imps.,

den fysiska bussen

I2C själv består av två ledningar. En I2C-linje sänder data, den andra klockan signalerar som synkroniserar konversationen mellan enheter. Datalinjen kallas ”SDA”, klocklinjen ”SCL”.

vanligtvis är både SDA och SCL anslutna till en 3.3 eller 5V kraftledning genom ett enda ”pull-up” – motstånd, en på varje rad. Detta är nödvändigt eftersom apparaternas SDA-och SCL-anslutningar är ”öppna avloppsledningar”: de kan tvinga spänningen på linjen till 0V eller ”låg”, men kan inte höja den till 3,3 V eller ”hög”., Hög och låg är de elektriska representationerna av 1s och 0s som är de grundläggande komponenterna i digital information. Att lägga till dessa två motstånd-och bussen behöver bara två, oavsett hur många enheter som är anslutna till den — säkerställer att spänningen stiger tillbaka till 3,3 V utan kortslutning.

I2C insisterar enheter har öppna avloppsledningar för att säkerställa att inga komponenter skadar höga strömmar kan flöda när två enheter försöker och signalera samtidigt.

i de flesta fall förväntas du själv lägga till dessa motstånd, men vissa enheter, vanligtvis de som arbetar vid 3.,3V, inkludera dem för att vara kompatibla med enheter som levererar 5V. kom ihåg att du bara behöver ett par dragmotstånd per buss, så det kan vara nödvändigt att ta bort dragmotstånd som är fästa på andra enheter på bussen. Även om imp har egna interna pull-up-motstånd, är dessa för svaga för att vara användbara för I2C och så inaktiveras de automatiskt när stiften är inställda för att hantera I2C-signaler.

styrenheter och kringutrustning

I2C-bussen separerar enheter i ”styrenheter” och ”kringutrustning”., Endast en enhet kan skicka ut tidspulser på SCL-linjen åt gången, och det är den som valts för att vara regulatorn. Alla andra synkroniserar sina tidpunkter till styrenheten, och anses därmed kringutrustning. Regulatorn-typiskt imp – och dess kringutrustning kan alla överföra och ta emot data, men endast regulatorn kan berätta en perifer när man ska överföra data tillbaka.

adressering

för att en I2C-enhet ska kunna kommunicera med en annan på en-till-en-basis måste båda enheterna vara unikt identifierbara. Denna identitet är enhetens I2C-adress., I2C-adresser är vanligtvis 7-bitarsnummer, så en buss kan bestå av upp till 127 enheter i alla. En byte består av åtta bitar; den extra biten används för att indikera om signalen skickas av regulatorn till perifer – a ”skriv” — eller i andra riktningen-a ”Läs”. Denna åttonde bit är faktiskt lite noll i Adress byte skickas ut på bussen. 7-bitarsadressen placeras i bitar en till sju av adressbyten.

i enlighet med detta format tar imp API en I2C-adresser som ett 8-bitarsvärde., Enhetsleverantörer ger vanligtvis sina produkters adresser som ett 7-bitars nummer, så det är nödvändigt att konvertera adressen från sju bitar till åtta. Detta uppnås med Squirrels<< operatör, som flyttar ett tals individuella bitarvärden till vänster. Denna process motsvarar att multiplicera med två. I kod ser den här processen ut så här:

local sevenBitAddress = 0x39;local eightBitAddress = sevenBitAddress << 1;

ekorre ställer automatiskt in Bit noll till rätt I2C-definierat värde: 0 för en skrivoperation, 1 för en läsning., Nu är du redo att använda en av imp: s i2c-metoder för att skriva data till bussen:

i2c.write(eightBitAddress, dataInStringForm);

7-bitarsadressen till den enhet som du vill att din imp ska kommunicera med kommer att levereras av komponentens tillverkare och listas på enhetens datablad. Det kan inte fixas, men väljs från en rad adresser enligt spänningen som appliceras på en annan av enheterna stiften., Till exempel har en Taos tsl2561 ljussensor tre möjliga adresser: 0x29, 0x49 eller 0x39, beroende på om addr-stiftet är fixerat vid 0V, 3.3 V eller ”flytande” mellan de två. Vi säger att värdet flyter eftersom det inte har valts aktivt för att fungera vid en viss spänning; Det kan vara allt från 0 till 3.3 V inklusive.

signalering

I2C bus-styrenheten använder en perifer 7-bitarsadress för att identifiera den komponent som den vill prata med., Faktum är att signaleringen är mer komplex än det, men lyckligtvis hanteras alla detaljer av imp så att du bara behöver ange adressen som ett 8-bitars värde.

om du skriver till periferin måste du också tillhandahålla data för att skriva, vilket ofta innehåller registervärden som instruerar kringutrustningen vad man ska göra med data. Imp-API-dokumentationen hänvisar till dessa register som”underadresser”:

i2c.write(eightBitAddress, dataString);

skriv() kräver data i strängform. Följaktligen kan du behöva konvertera värdet som lagras i andra typer av variabel till strängform.,

läsa information från en enhet kan kräva ett kommando för att tala om för enheten vilka data som ska hämtas. Att tala om för imp att läsa data från I2C-bussen innebär också att tillhandahålla en tredje parameter, antalet byte du förväntar dig att ta emot:

i2c.read(eightBitAddress, controlDataString, numberOfBytesToRead);

bakom dessa operationer är I2C: s elektriska signaler, applicerade på SDA-linjen synkroniserad med tidspulserna som appliceras på SCL-linjen. Att skriva till bussen innebär en startmarkör: släppa SDA till 0V medan SCL är 3.3 V. ändra SDA-spänningen när SCL: s spänning är hög definierar start-och stoppmarkörer., Om SDA-spänningen inte ändras medan SCL är hög, vet I2C-enheter att data, snarare än markörer, skickas.

SDA går nu högt eller lågt för att skicka ut varje bit av adressbyten: 7-bitars enhetsadressen följt av läs – /skrivbiten. Byte bitar skickas ut vänster-mest bit – den ” mest signifikanta biten — – först, med SDA går högt om bitens värde är 1 eller lågt om det är noll. Målets periferi kommer nu att dra SDA low för att signalera bekräftelse på mottagandet av data, och sedan ut går åtta bitar kontrollinformation eller data, följt av mer data om det behövs., Det finns en enda puls ” ack ” bekräftelse paus på SDA mellan varje åtta bitar skickas, tidsinställd till en nionde SCL puls. Om perifer inte bekräftar kvittot på detta sätt, kommer styrenheten att upptäcka att SDA har varit hög och kommer att signalera ett fel.,

När data strömmar från det perifera till den registeransvarige, den senare också bekräftar mottagandet av åtta bitar genom att dra SDA låg på den nionde SCL puls om detta inte är den sista byte av en sats, i vilket fall styrenheten inte drar SDA låg – det gör en ” nak ”signal ,eller” ingen bekräftelse ” — för att låta det perifera vet att det har slutförts.

När vi är klara, SDA går högt som en stoppmarkering.,


start av överföringen indikeras av SDA släppa från hög till låg spänning (rektangeln till vänster),
stoppa av den omvända (den högra rektangeln). SCL måste vara hög när detta sker

Timing

standardklockhastigheten för I2C — kommunikation är 100kHz-100,000 SCL-pulser per sekund. Det är möjligt att gå snabbare, upp till 400kHz. Vissa enheter kanske inte kan stödja denna hastighet. kontrollera databladet som följer med den enhet du vill ansluta till din imp., Men många långsamma enheter använder en teknik som kallas ”clock stretching” för att tvinga snabbare enheter att arbeta till sin hastighet. Imp stöder enheter som använder sig av denna teknik. I huvudsak håller de SCL låg medan de hämtar de data du vill att de ska skicka till imp. Imp upptäcker detta, släpper SCL-linjen och väntar tills SCL går högt igen innan du fortsätter.

Du kan dock behöva sänka I2C-hastigheten själv om de elektriska egenskaperna hos din inställning saktar hastigheten på övergången mellan 0V och 3.3 V, kallad ”stigtiden”., Detta orsakas ofta av långa ledningar, vilket ökar kretsens kapacitans. För att enheterna ska kunna upptäcka överföringen av varje bit måste bussen springa långsammare. Data korruption eller oväntade resultat är ledtrådar du bör se upp för. Minska I2C-busshastigheten tills data läses framgångsrikt.

imp API tillhandahåller för närvarande fyra fördefinierade klockvärden: 10, 50 100 och 400kHz., De är utvalda genom att anta en konstant till I2C-konfiguration metoden som en parameter:

i2c.configure(speedConstant);

där värdet av speedConstant är en av

  • CLOCK_SPEED_10_KHZ
  • CLOCK_SPEED_50_KHz
  • CLOCK_SPEED_100_KHZ
  • CLOCK_SPEED_400_KHZ

om inrättande av En integrerad havspolitik För I2C

I2c-objekt i exemplet rader kod som anges ovan är inte lämnas direkt av imp, men som du har valt enligt vilka av dina valda imp ’ s stift du kommer att använda för I2C-kommunikation., Varje typ av imp har flera I2C bussar, alla tillgängliga vid start. Kolla in pin mux för den typ av imp du använder för att se vilka I2C-objekt som är tillgängliga för dig. Här antar vi att du använder en imp001. Den imp001 två I2C-buss finns på stift 1 och 2 och stift 8 och 9, respektive instanser som egenskaper i2c12 och i2c89 av hårdvara objekt när imp startar upp. Stift 1 och 8 är tilldelade till SCL, 2 och 9 till SDA.,

det är vanligt att referera till ditt val med en global variabel:

i2c <- hardware.i2c12;i2c.configure(CLOCK_SPEED_100_KHZ);

exempelkod

följande kod fungerar med Taos tsl2561 synlig och infraröd ljussensor, en 3,3 V-enhet som använder I2C för att kommunicera med sin värdmikrokontroller. Chipets datablad kan laddas ner från adafruits webbplats. Adafruit säljer chip på en låg kostnad breakout ombord som innehåller lämpliga pull-up motstånd på power pin, VCC. Det betyder att den är redo att ansluta direkt till en imp: s I2C-stift.,


adafruits tsl2561 breakout board

Observera efter att denna artikel skrevs uppdaterade Adafruit sitt tsl2561-sensorkort. Den nya versionen Fungerar med den aktuella koden.

här är koden, för agenten och sedan enheten:

vad koden gör

agentkoden svarar på en inkommande HTTP-förfrågan genom att meddela enheten att den kräver en läsning. För enkelhetens skull visas läsningen helt enkelt i loggen.

enhetskoden läser sensorn och beräknar ett lux-värde enligt den matte som anges i tsl2561-databladet., Den första delen av programmet ställer in konstanter för tsl2561 nyckelregister och inställningar, inklusive dess I2C-adressalternativ. Andra konstanter används i luminositetsomvandlingsprocessen.


Wiring up the imp

vid programstartpunkten, kod Alias en av imp: s I2C pin set som en global variabel, konfigurerar busshastigheten till 100kHz och sedan skiftar tsl2561 s I2C adress en bit till vänster så det är redo att användas med imp I2C funktioner. Det sätter sedan upp sensorn., Bara för att kontrollera att detta har fungerat läser vi kontrollregistret: returvärdet ska vara 3 om TSL2561 just har startat, eller 51 om enheten redan har slagits på.

därefter ställer koden in sensorns ADC-upplösning genom tsl2561: s tidsregister och ställer sedan in signalförstärkningen till hög.

slutligen berättar vi imp hur man svarar på"sense" meddelanden från agenten. Detta kallar en funktion som läser tsl2561: s två ljussensorer, digitala värden för vilka lagras i chipets fyra 8-bitars ADC-register., De två första ger en 16-bitars kombinerad optisk och infraröd läsning, det andra paret ett 16-bitars IR-bara värde. Funktionerna readSensorAdc0() och readSensorAdc1 () omvandlar de enskilda registervärdena till 16-bitars tal genom att multiplicera den mest signifikanta byte med 256 och lägga till värdet av den minst signifikanta byte. Multiplikationen utförs genom att flytta åttabitarnummerets bitar lämnade åtta platser med ekorrens<< operatör.,

koden ger sedan båda dessa avläsningar till en tredje funktion för att beräkna en slutlig ljusstyrka, ” lux ” – värde.

Ytterligare läsning

  • I2C fel — Hur felsöka I2C läsa och skriva problem

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *