Using The I2C Bus
Using The I2C Bus
1 9
UsingtheI2CBus
Judgingfrommyemails,itisquiteclearthattheI2Cbuscanbevery confusingforthenewcomer.IhavelotsofexamplesonusingtheI2Cbus onthewebsite,butmanyoftheseareusinghighlevelcontrollersanddo notshowthedetailofwhatisactuallyhappeningonthebus.Thisshort articlethereforetriestode-mystifytheI2Cbus,Ihopeitdoesn'thavethe oppositeeffect! The physical I2C bus Thisisjusttwowires,calledSCLandSDA.SCListheclockline.Itis usedtosynchronizealldatatransfersovertheI2Cbus.SDAisthedata line.TheSCL&SDAlinesareconnectedtoalldevicesontheI2Cbus. Thereneedstobeathirdwirewhichisjustthegroundor0volts.There mayalsobea5voltwireispowerisbeingdistributedtothedevices.Both SCLandSDAlinesare"opendrain"drivers.Whatthismeansisthatthe chipcandriveitsoutputlow,butitcannotdriveithigh.Forthelinetobe abletogohighyoumustprovidepull-upresistorstothe5vsupply.There shouldbearesistorfromtheSCLlinetothe5vlineandanotherfromthe SDAlinetothe5vline.Youonlyneedonesetofpull-upresistorsforthe wholeI2Cbus,notforeachdevice,asillustratedbelow:
Thevalueoftheresistorsisnotcritical.Ihaveseenanythingfrom1k8 (1800ohms)to47k(47000ohms)used.1k8,4k7and10karecommon values,butanythinginthisrangeshouldworkOK.Irecommend1k8as thisgivesyouthebestperformance.Iftheresistorsaremissing,theSCL andSDAlineswillalwaysbelow-nearly0volts-andtheI2Cbuswillnot work. Masters and Slaves ThedevicesontheI2Cbusareeithermastersorslaves.Themasteris alwaysthedevicethatdrivestheSCLclockline.Theslavesarethedevices thatrespondtothemaster.AslavecannotinitiateatransferovertheI2C bus,onlyamastercandothat.Therecanbe,andusuallyare,multiple
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
2 9
slavesontheI2Cbus,howeverthereisnormallyonlyonemaster.Itis possibletohavemultiplemasters,butitisunusualandnotcoveredhere. Onyourrobot,themasterwillbeyourcontrollerandtheslaveswillbeour modulessuchastheSRF08orCMPS03.Slaveswillneverinitiatea transfer.BothmasterandslavecantransferdataovertheI2Cbus,butthat transferisalwayscontrolledbythemaster. The I2C Physical Protocol Whenthemaster(yourcontroller)wishestotalktoaslave(ourCMPS03 forexample)itbeginsbyissuingastartsequenceontheI2Cbus.Astart sequenceisoneoftwospecialsequencesdefinedfortheI2Cbus,theother beingthestopsequence.Thestartsequenceandstopsequencearespecial inthatthesearetheonlyplaceswheretheSDA(dataline)isallowedto changewhiletheSCL(clockline)ishigh.Whendataisbeingtransferred, SDAmustremainstableandnotchangewhilstSCLishigh.Thestartand stopsequencesmarkthebeginningandendofatransactionwiththeslave device.
Dataistransferredinsequencesof8bits.ThebitsareplacedontheSDA linestartingwiththeMSB(MostSignificantBit).TheSCLlineisthen pulsedhigh,thenlow.Rememberthatthechipcannotreallydrivetheline high,itsimply"letsgo"ofitandtheresistoractuallypullsithigh.For every8bitstransferred,thedevicereceivingthedatasendsbackan acknowledgebit,sothereareactually9SCLclockpulsestotransfereach8 bitbyteofdata.IfthereceivingdevicesendsbackalowACKbit,thenit hasreceivedthedataandisreadytoacceptanotherbyte.Ifitsendsbacka highthenitisindicatingitcannotacceptanyfurtherdataandthemaster shouldterminatethetransferbysendingastopsequence.
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
3 9
whichisupto3.4MHz.Allofourmodulesaredesignedtoworkatupto 100KHz.Wehavetestedourmodulesupto1MHzbutthisneedsasmall delayofafewuSbetweeneachbytetransferred.Inpracticalrobots,we haveneverhadanyneedtousehighSCLspeeds.KeepSCLatorbelow 100KHzandthenforgetaboutit. I2C Device Addressing AllI2Caddressesareeither7bitsor10bits.Theuseof10bitaddressesis rareandisnotcoveredhere.Allofourmodulesandthecommonchipsyou willusewillhave7bitaddresses.Thismeansthatyoucanhaveupto128 devicesontheI2Cbus,sincea7bitnumbercanbefrom0to127.When sendingoutthe7bitaddress,westillalwayssend8bits.Theextrabitis usedtoinformtheslaveifthemasteriswritingtoitorreadingfromit.If thebitiszeroaremasteriswritingtotheslave.Ifthebitis1themasteris readingfromtheslave.The7bitaddressisplacedintheupper7bitsofthe byteandtheRead/Write(R/W)bitisintheLSB(LeastSignificantBit).
Theplacementofthe7bitaddressintheupper7bitsofthebyteisasource ofconfusionforthenewcomer.Itmeansthattowritetoaddress21,you mustactuallysendout42whichis21movedoverby1bit.Itisprobably easiertothinkoftheI2Cbusaddressesas8bitaddresses,witheven addressesaswriteonly,andtheoddaddressesasthereadaddressforthe samedevice.TotakeourCMPS03forexample,thisisataddress0xC0 ($C0).Youwoulduses0xC0towritetotheCMPS03and0xC1toread fromit.Sotheread/writebitjustmakesitanodd/evenaddress. The I2C Software Protocol Thefirstthingthatwillhappenisthatthemasterwillsendoutastart sequence.Thiswillalertalltheslavedevicesonthebusthatatransactionis startingandtheyshouldlisteninincaseitisforthem.Nextthemasterwill sendoutthedeviceaddress.Theslavethatmatchesthisaddresswill continuewiththetransaction,anyotherswillignoretherestofthis transactionandwaitforthenext.Havingaddressedtheslavedevicethe mastermustnowsendouttheinternallocationorregisternumberinside theslavethatitwishestowritetoorreadfrom.Thisnumberisobviously dependantonwhattheslaveactuallyisandhowmanyinternalregistersit has.Someverysimpledevicesdonothaveany,butmostdo,includingall ofourmodules.OurCMPS03has16locationsnumbered0-15.TheSRF08
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
4 9
has36.HavingsenttheI2Caddressandtheinternalregisteraddressthe mastercannowsendthedatabyte(orbytes,itdoesn'thavetobejustone). Themastercancontinuetosenddatabytestotheslaveandthesewill normallybeplacedinthefollowingregistersbecausetheslavewill automaticallyincrementtheinternalregisteraddressaftereachbyte.When themasterhasfinishedwritingalldatatotheslave,itsendsastopsequence whichcompletesthetransaction.Sotowritetoaslavedevice: 1.Sendastartsequence 2.SendtheI2CaddressoftheslavewiththeR/Wbitlow(evenaddress) 3.Sendtheinternalregisternumberyouwanttowriteto 4.Sendthedatabyte 5.[Optionally,sendanyfurtherdatabytes] 6.Sendthestopsequence. Asanexample,youhaveanSRF08atthefactorydefaultaddressof0xE0. TostarttheSRF08rangingyouwouldwrite0x51tothecommandregister at0x00likethis: 1.Sendastartsequence 2.Send0xE0(I2CaddressoftheSRF08withtheR/Wbitlow(even address) 3.Send0x00(Internaladdressofthecommandregister) 4.Send0x51(ThecommandtostarttheSRF08ranging) 5.Sendthestopsequence. Reading from the Slave Thisisalittlemorecomplicated-butnottoomuchmore.Beforereading datafromtheslavedevice,youmusttellitwhichofitsinternaladdresses youwanttoread.Soareadoftheslaveactuallystartsoffbywritingtoit. Thisisthesameaswhenyouwanttowritetoit:Yousendthestart sequence,theI2CaddressoftheslavewiththeR/Wbitlow(evenaddress) andtheinternalregisternumberyouwanttowriteto.Nowyousend anotherstartsequence(sometimescalledarestart)andtheI2Caddress again-thistimewiththereadbitset.Youthenreadasmanydatabytesas youwishandterminatethetransactionwithastopsequence.Sotoreadthe compassbearingasabytefromtheCMPS03module: 1.Sendastartsequence 2.Send0xC0(I2CaddressoftheCMPS03withtheR/Wbitlow(even address) 3.Send0x01(Internaladdressofthebearingregister) 4.Sendastartsequenceagain(repeatedstart) 5.Send0xC1(I2CaddressoftheCMPS03withtheR/Wbithigh(odd
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
5 9
Wait a moment That'salmostitforsimpleI2Ccommunications,butthereisonemore complication.Whenthemasterisreadingfromtheslave,itstheslavethat placesthedataontheSDAline,butitsthemasterthatcontrolstheclock. Whatiftheslaveisnotreadytosendthedata!Withdevicessuchas EEPROMsthisisnotaproblem,butwhentheslavedeviceisactuallya microprocessorwithotherthingstodo,itcanbeaproblem.The microprocessorontheslavedevicewillneedtogotoaninterruptroutine, saveitsworkingregisters,findoutwhataddressthemasterwantstoread from,getthedataandplaceitinitstransmissionregister.Thiscantake manyuStohappen,meanwhilethemasterisblissfullysendingoutclock pulsesontheSCLlinethattheslavecannotrespondto.TheI2Cprotocol providesasolutiontothis:theslaveisallowedtoholdtheSCLlinelow! Thisiscalledclockstretching.Whentheslavegetsthereadcommandfrom themasteritholdstheclocklinelow.Themicroprocessorthengetsthe requesteddata,placesitinthetransmissionregisterandreleasestheclock lineallowingthepull-upresistortofinallypullithigh.Fromthemasters pointofview,itwillissuethefirstclockpulseofthereadbymakingSCL highandthenchecktoseeifitreallyhasgonehigh.Ifitsstilllowthenits theslavethatholdingitlowandthemastershouldwaituntilitgoeshigh beforecontinuing.LuckilythehardwareI2Cportsonmostmicroprocessors willhandlethisautomatically. Sometimeshowever,themasterI2Cisjustacollectionofsubroutinesand thereareafewimplementationsouttherethatcompletelyignoreclock stretching.TheyworkwiththingslikeEEPROM'sbutnotwith microprocessorslavesthatuseclockstretching.Theresultisthaterroneous
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus dataisreadfromtheslave.Beware!
6 9
Example Master Code ThisexampleshowshowtoimplementasoftwareI2Cmaster,including clockstretching.ItiswritteninCforthePICprocessor,butshouldbe applicabletomostprocessorswithminorchangestotheI/Opindefinitions. ItissuitableforcontrollingallofourI2Cbasedrobotmodules.Sincethe SCLandSDAlinesareopendraintype,weusethetristatecontrolregister tocontroltheoutput,keepingtheoutputregisterlow.Theportpinsstill needtobereadthough,sothey'redefinedasSCL_INandSDA_IN.This definitionandtheinitializationisprobablyallyou'llneedtochangefora differentprocessor. #define #define #define #define SCL SDA SCL_IN SDA_IN TRISB4 TRISB1 RB4 RB1 // I2C bus // // //
Toinitializetheportssettheoutputresistersto0andthetristateregistersto 1whichdisablestheoutputsandallowsthemtobepulledhighbythe resistors. SDA = SCL = 1; SCL_IN = SDA_IN = 0; WeuseasmalldelayroutinebetweenSDAandSCLchangestogivea clearsequenceontheI2Cbus.Thisisnothingmorethanasubroutinecall andreturn. void i2c_dly(void) { } Thefollowing4functionsprovidetheprimitivestart,stop,readandwrite sequences.AllI2Ctransactionscanbebuiltupfromthese. void i2c_start(void) { SDA = 1; // i2c start bit sequence i2c_dly(); SCL = 1; i2c_dly(); SDA = 0;
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
7 9
i2c_dly(); SCL = 0; i2c_dly(); } void i2c_stop(void) { SDA = 0; // i2c stop bit sequence i2c_dly(); SCL = 1; i2c_dly(); SDA = 1; i2c_dly(); } unsigned char i2c_rx(char ack) { char x, d=0; SDA = 1; for(x=0; x<8; x++) { d <<= 1; do { SCL = 1; } while(SCL_IN==0); // wait for any SCL clock stretching i2c_dly(); if(SDA_IN) d |= 1; SCL = 0; } if(ack) SDA = 0; else SDA = 1; SCL = 1; i2c_dly(); // send (N)ACK bit SCL = 0; SDA = 1; return d; }
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
8 9
bit i2c_tx(unsigned char d) { char x; static bit b; for(x=8; x; x--) { if(d&0x80) SDA = 1; else SDA = 0; SCL = 1; d <<= 1; SCL = 0; } SDA = 1; SCL = 1; i2c_dly(); b = SDA_IN; // possible ACK bit SCL = 0; return b; } The4primitivefunctionsabovecaneasilybeputtogethertoform completeI2Ctransactions.Here'sandexampletostartanSRF08rangingin cm: i2c_start(); i2c_tx(0xE0); clear i2c_tx(0x00); i2c_tx(0x51); i2c_stop(); // send start sequence // SRF08 I2C address with R/W bit // SRF08 command register address // command to start ranging in cm // send stop sequence
Nowafterwaiting65mSfortherangingtocomplete(I'veleftthattoyou) thefollowingexampleshowshowtoreadthelightsensorvaluefrom register1andtherangeresultfromregisters2&3. i2c_start(); // send start sequence i2c_tx(0xE0); // SRF08 I2C address with R/W bit clear i2c_tx(0x01); // SRF08 light sensor register address
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012
UsingtheI2CBus
9 9
i2c_start(); // send a restart sequence i2c_tx(0xE1); // SRF08 I2C address with R/W bit set lightsensor = i2c_rx(1); // get light sensor and send acknowledge. Internal register address will increment automatically. rangehigh = i2c_rx(1); // get the high byte of the range and send acknowledge. rangelow = i2c_rx(0); // get low byte of the range note we don't acknowledge the last byte. i2c_stop(); // send stop sequence Easyisn'tit? ThedefinitivespecsontheI2CbuscanbefoundonthePhilipswebsite.It currentlyherebutifitsmovedyou'llfinditeasilybegoogleingon"i2cbus specification".
file://J:\Arduino\Html\UsingtheI2CBus.htm
25/6/2012