De Inter-Integrated Circuit (I2C) bus is een chip-level seriële communicatie mechanisme dat werkt over slechts twee draden. Sommige ontwikkelaars spreken de naam eye-two-see uit, anderen eye-squared-see, maar beide verwijzen naar hetzelfde. Bedacht door Philips in de vroege jaren 1980, I2C werd opgericht om de communicatie tussen de chips van het bedrijf te standaardiseren, maar het is sindsdien uitgegroeid tot een de facto standaard ondersteund door vele Microcontroller apparaten van Arduino boards aan de Raspberry Pi en, natuurlijk, imps.,
de fysieke Bus
I2C zelf bestaat uit twee draden. De ene I2C-lijn verzendt gegevens, de andere de kloksignalen die het gesprek tussen apparaten synchroniseren. De datalijn heet ‘SDA’, de kloklijn ‘SCL’.
gewoonlijk zijn zowel SDA als SCL aangesloten op een 3.3-of 5V-stroomleiding via één pull-up-weerstand, één op elke lijn. Dit is nodig omdat de SDA-en SCL-aansluitingen van apparaten’ open drain ‘ – lijnen zijn: ze kunnen de spanning op de lijn forceren tot 0V, of ‘laag’, maar niet verhogen tot 3,3 V, of ‘hoog’., Hoog en laag zijn de elektrische representaties van de 1s en 0s die de fundamentele componenten zijn van digitale informatie. Het toevoegen van deze twee weerstanden — en de bus heeft er maar twee nodig, ongeacht hoeveel apparaten er op zijn aangesloten — zorgt ervoor dat de spanning zonder kortsluiting weer stijgt naar 3,3 V.
I2C dringt erop aan dat apparaten open afvoerleidingen hebben om ervoor te zorgen dat geen component-schadelijke hoge stromen kunnen stromen wanneer twee apparaten gelijktijdig proberen te signaleren.
in de meeste gevallen wordt verwacht dat u deze weerstanden zelf toevoegt, maar sommige apparaten, meestal die welke op 3 werken.,3v, neem ze op om compatibel te zijn met apparaten die 5V leveren. vergeet niet dat u slechts een paar pull-up weerstanden per bus nodig hebt, dus het kan nodig zijn om pull-up weerstanden te verwijderen die aan andere apparaten op de bus zijn bevestigd. Hoewel de imp interne pull-up weerstanden van zijn eigen, Deze zijn te zwak om nuttig te zijn voor I2C en dus worden ze automatisch uitgeschakeld wanneer de pinnen zijn ingesteld om I2C signalen te verwerken.
Controllers en randapparatuur
de I2C-bus scheidt apparaten in ‘ controllers ‘en’randapparatuur’., Slechts één apparaat kan timing pulsen sturen op de SCL lijn per keer, en dat is degene die gekozen is om de controller te zijn. Alle anderen synchroniseren hun timings met de controller, en worden dus beschouwd als randapparatuur. De controller-meestal de imp – en zijn randapparatuur kunnen allemaal gegevens verzenden en ontvangen, maar alleen de controller kan een perifeer vertellen wanneer gegevens moeten worden teruggestuurd.
adressering
om een I2C-apparaat één-op-één met een ander te laten communiceren, moeten beide apparaten uniek identificeerbaar zijn. Deze identiteit is het I2C-adres van het apparaat., I2C adressen zijn meestal 7-bit nummers, dus een bus kan tot 127 apparaten in totaal. Een byte bestaat uit acht bits; het extra bit wordt gebruikt om aan te geven of het signaal door de controller naar de rand wordt gestuurd — een ‘schrijven’ — of in de andere richting — een ‘lezen’. Deze achtste bit is eigenlijk bit nul in de adresbyte verzonden naar de bus. Het 7-bits adres wordt geplaatst in bits één tot en met zeven van de adresbyte.
in overeenstemming met dit formaat neemt de imp API een I2C-adressen als een 8-bit waarde., Apparaatleveranciers geven meestal de adressen van hun producten op als een 7-bit-nummer, dus het is noodzakelijk om het adres van zeven bits naar acht om te zetten. Dit wordt bereikt met Squirrel ’s <<
operator, die de individuele bitwaarden van een nummer naar links verplaatst. Dit proces is het equivalent van vermenigvuldigen met twee. In code ziet dit proces er als volgt uit:
local sevenBitAddress = 0x39;local eightBitAddress = sevenBitAddress << 1;
Eekhoorn stelt bit nul automatisch in op de juiste I2C-gedefinieerde waarde: 0 voor een schrijfbewerking, 1 voor een lezen., Nu bent u klaar om een van de I2C-methoden van de imp te gebruiken om gegevens naar de bus te schrijven:
i2c.write(eightBitAddress, dataInStringForm);
het 7-bits adres van het apparaat waaraan u wilt communiceren met de imp wordt geleverd door de fabrikant van de component en vermeld op het datasheet van het apparaat. Het kan niet worden vastgesteld, maar geselecteerd uit een reeks adressen volgens de spanning toegepast op een andere van de apparaten pinnen., Een TAOS TSL2561-lichtsensor heeft bijvoorbeeld drie mogelijke adressen: 0x29
, 0x49
of 0x39
, afhankelijk van of de addr-pin op 0V, 3,3 V of ‘zwevend’ tussen de twee is bevestigd. We zeggen dat de waarde drijft omdat het niet actief is geselecteerd om te werken op een specifieke spanning; het kan om het even wat van 0 tot 3.3 V inclusief zijn.
signalering
de controller van de I2C-bus gebruikt het 7-bit-adres van een randapparaat om het component te identificeren waarmee het wil praten., In feite is de signalering complexer dan dat, maar gelukkig worden alle details afgehandeld door de imp zodat u alleen het adres als een 8-bit waarde hoeft op te geven.
als je naar het randapparaat schrijft, moet je ook de gegevens opgeven om te schrijven, wat vaak registerwaarden bevat die de randapparatuur instrueren wat ze met de gegevens moeten doen. De imp API documentatie verwijst naar deze registers als ‘sub-adressen’:
i2c.write(eightBitAddress, dataString);
write() vereist gegevens in string vorm. Daarom moet u mogelijk de waarde die is opgeslagen in andere soorten variabelen converteren naar stringvorm.,
Het lezen van informatie van een apparaat kan een commando vereisen om het apparaat te vertellen welke gegevens moeten worden opgehaald. Het vertellen van de imp om gegevens van de I2C bus te lezen impliceert ook het verstrekken van een derde parameter, het aantal bytes dat u verwacht te ontvangen:
i2c.read(eightBitAddress, controlDataString, numberOfBytesToRead);
achter deze operaties zijn de elektrische signalen van de I2C, toegepast op de SDA lijn gesynchroniseerd met de timing pulsen toegepast op de SCL lijn. Het schrijven naar de bus impliceert een startmarker: het laten vallen van SDA naar 0V terwijl SCL 3.3 V. het veranderen van de SDA-spanning wanneer de spanning van de SCL hoog is definieert start-en stopmarkeringen., Als de SDA-spanning niet verandert terwijl SCL hoog is, weten I2C-apparaten dat gegevens, in plaats van markers, worden verzonden.
SDA gaat nu hoog of laag om elk bit van de adresbyte te verzenden: het 7-bit apparaatadres gevolgd door de lees – /schrijfbit. De bits van de byte worden eerst links-meest Bit — het ‘meest significante bit’ — verzonden, waarbij SDA hoog gaat als de waarde van de bit 1 is of laag als het nul is. De doelrand zal nu SDA low trekken om bevestiging van ontvangst van de gegevens aan te geven, en dan gaat er acht bits controle-informatie of gegevens uit, gevolgd door meer gegevens indien nodig., Er is een enkele-puls ‘ack’ bevestiging pauze op SDA tussen elke acht bits verzonden, getimed tot een negende SCL puls. Als de randapparatuur de ontvangst niet op deze manier bevestigt, zal de controller detecteren dat de SDA hoog is gebleven en een fout signaleren.,
wanneer gegevens van de randapparatuur naar de controller stromen, bevestigt deze ook de ontvangst van acht bits door SDA laag te trekken op de negende SCL — puls, tenzij dit de laatste byte van een batch is, in welk geval de controller geen SDA laag trekt — het maakt een ‘nak’ – signaal, of ‘geen bevestiging’ – om de randapparatuur te laten weten dat het klaar is.
als we klaar zijn, gaat SDA hoog als een stopmarker.,
het begin van de transmissie wordt aangegeven door SDA die daalt van hoog naar laag voltage (de rechthoek aan de linkerkant),
stop door de omgekeerde (de rechthoek). SCL moet hoog zijn wanneer dit plaatsvindt
Timing
De standaard kloksnelheid voor I2C-communicatie is 100kHz-100.000 SCL-pulsen per seconde. Het is mogelijk om sneller te gaan, tot 400kHz. Sommige apparaten kunnen deze snelheid mogelijk niet ondersteunen; controleer de datasheet die het apparaat vergezelt dat u met uw imp wilt verbinden., Echter, veel langzame apparaten gebruiken een techniek genaamd ‘klok stretching’ om snellere apparaten te dwingen om te werken aan hun snelheid. De imp ondersteunt apparaten die gebruik maken van deze techniek te maken. In wezen houden ze SCL laag terwijl ze de gegevens ophalen die je wilt dat ze naar de imp sturen. De imp detecteert dit, geeft de SCL lijn vrij en wacht tot SCL weer hoog gaat alvorens verder te gaan.
Het kan echter nodig zijn om de I2C-snelheid zelf te verlagen als de elektrische eigenschappen van uw set-up de snelheid van de overgang tussen 0V en 3,3 V, de ‘stijgtijd’genoemd, vertragen., Dit wordt vaak veroorzaakt door lange draden, die de capaciteit van het circuit verhogen. Om ervoor te zorgen dat de apparaten met succes de overdracht van elk bit detecteren, moet de bus langzamer lopen. Data corruptie of onverwachte resultaten zijn de aanwijzingen die u moet uitkijken voor. Verminder de snelheid van de I2C-bus totdat de gegevens met succes worden gelezen.
De imp API biedt momenteel vier vooraf gedefinieerde klokwaarden: 10, 50 100 en 400kHz., Ze zijn geselecteerd door het passeren van een constante om de I2C-configuratie methode als een parameter:
i2c.configure(speedConstant);
waar de waarde van speedConstant is een van
- CLOCK_SPEED_10_KHZ
- CLOCK_SPEED_50_KHz
- CLOCK_SPEED_100_KHZ
- CLOCK_SPEED_400_KHZ
het Instellen van Een gvo Voor I2C
De i2c-object in het voorbeeld lijnen van code hierboven gegeven wordt niet rechtstreeks door de imp, maar de door u gekozen afhankelijk van uw gekozen imp ‘ s pinnen die je zult gebruiken voor I2C communicatie., Elk type imp heeft meerdere I2C-bussen, allemaal beschikbaar gesteld bij het opstarten. Bekijk de pin mux voor het type imp dat u gebruikt om te zien welke I2C objecten voor u beschikbaar zijn. We nemen aan dat je een imp001 gebruikt. De twee I2C-bussen van de imp001 staan op pinnen 1 en 2, en pinnen 8 en 9, respectievelijk geïnstalleerd als eigenschappen i2c12 en i2c89 van het hardware-object wanneer de imp opstart. Pinnen 1 en 8 zijn toegewezen aan SCL, 2 en 9 aan SDA.,
Het is gebruikelijk om naar uw keuze te verwijzen met een globale variabele:
i2c <- hardware.i2c12;i2c.configure(CLOCK_SPEED_100_KHZ);
voorbeeldcode
De volgende code werkt met de TAOS TSL2561 visible and infrared light sensor, een 3.3 V apparaat dat I2C gebruikt om te communiceren met zijn Host microcontroller. De datasheet van de chip kan worden gedownload van de Adafruit website. Adafruit verkoopt de chip op een low-cost breakout board die geschikte pull-up weerstanden op de macht pin, VCC omvat. Dit betekent dat het klaar is om direct aan te sluiten op de I2C-spelden van een imp.,
Adafruit ‘ s TSL2561 breakout board
Note nadat dit artikel geschreven was, heeft Adafruit zijn TSL2561 sensor board bijgewerkt. De nieuwe versie werkt met de huidige code.
Hier is de code, voor de agent en vervolgens het apparaat:
wat de Code doet
De agentcode reageert op een binnenkomende HTTP-aanvraag door het apparaat te melden dat het een lezing vereist. Voor de eenvoud wordt het lezen gewoon weergegeven in het logboek.
De apparaatcode leest de sensor en berekent een lux-waarde volgens de wiskunde die is vastgelegd in het TSL2561-gegevensblad., Het eerste deel van het programma stelt constanten op voor de sleutelregisters en instellingen van de TSL2561, inclusief de I2C-adresopties. Andere constanten worden gebruikt in het lichtkrachtconversieproces.
Het opzetten van de imp
bij het startpunt van het programma aliased de code een van de imp ‘ s I2C-pin ingesteld als een globale variabele, configureert de bussnelheid tot 100kHz en verschuift dan het I2C-adres van de TSL2561 een bit naar links zodat het klaar is voor gebruik met de imp I2C-functies. Vervolgens wordt de sensor ingesteld., Om te controleren of dit heeft gewerkt, lezen we het control register: de retourwaarde moet 3 zijn als de TSL2561 net is gestart, of 51 als het apparaat al is ingeschakeld.
Vervolgens stelt de code de ADC-resolutie van de sensor in via het timingregister van de TSL2561 en stelt vervolgens de signaalversterking in op hoog.
tot slot vertellen we de imp hoe te reageren op "sense"
meldingen van de agent. Dit roept een functie op die de twee lichtsensoren van de TSL2561 leest, waarvan de digitale waarden worden opgeslagen in de vier 8-bit ADC registers van de chip., De eerste twee geven een 16-bit gecombineerde optische en infrarode uitlezing, het tweede paar een 16-bit ir-only waarde. De functies readSensorAdc0() en readSensorAdc1() zetten de individuele registerwaarden om in 16-bits getallen door de meest significante byte met 256 te vermenigvuldigen en de waarde van de minst significante byte toe te voegen. De vermenigvuldiging wordt uitgevoerd door het verschuiven van de bits van het acht-bits getal acht plaatsen links met Eekhoorn ’s << operator.,
de code levert vervolgens beide metingen aan een derde functie om een uiteindelijke helderheid, ” lux ” – waarde, te berekenen.
verder lezen
- I2C fouten-hoe debuggen I2C lees-en schrijfproblemen