• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » Stellaris® ARM® Microcontrollers » Stellaris® ARM® LM3S Microcontrollers Forum » I2C HANDLING by EVALBOT
Share
Stellaris® ARM® Microcontrollers
  • Forum
Options
  • Subscribe via RSS
Helpful Stellaris® LM4F Series Links
  • LM4F Series
  • Stellaris PinMux Utility
  • Stellaris® LM4F120 LaunchPad
  • LM4F MCU Applications
  • LM4F MCU Video
  • ARM Cortex-M4F Whitepaper
  • Stellaris MCU Brochure
  • LM4F232 Eval Kit
  • Forums

    I2C HANDLING by EVALBOT

    This question is answered
    A Newbie
    Posted by A Newbie
    on Apr 25 2012 05:37 AM
    Prodigy150 points

    Hello All, 

    I'm trying to implement an I2C communication using EVALBOT. Evalbot is the master which has to continuously receive date from slave. 

    Can someone please give me rough sketch of the algorithm to be used. Do I need to send acknowledge after receiving each byte ? Or will the I2CMasterDataGet() function do it on its own? Is it possible to continuously keep on reading (and store each byte), rather than reading byte by byte?

    Any help will be very much appreciated.

    Thanks

    EVALBOT ARM Cortex M3 i2c communication
    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • cb1_mobile
      Posted by cb1_mobile
      on Apr 25 2012 07:29 AM
      Verified Answer
      Verified by A Newbie
      Guru21870 points

      Past post - blessed both by Stellaris Sue & independent forum user - provides I2C set-up/guidance from both TI responder and this reporter.

      http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/p/169023/639164.aspx#639164

      The "ACKs" (and dreaded NAKs) are generated automatically by the I2C functions provided by TI's StellarisWare.  Suspect that continuous reading of I2C Slave is at least somewhat dependent upon that specific slave.  (for instance - I know that many EEproms auto increment their address and may "dump" their entire "guts" without requiring the "full" I2C transaction "initiator" to be re-sent)

      I2C is well covered w/in StellarisWare (entire chapter), MCU datasheet, and numerous software examples are provided.  (look both in examples and peripheral folders of StellarisWare...

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • A Newbie
      Posted by A Newbie
      on Apr 26 2012 04:57 AM
      Prodigy150 points

      Thanks for your reply. 

      I tried studying all the example codes in StellarisWare. 

      // Set the address for slave module. This is a 7-bit address sent in the
      // following format:
      // [A6:A5:A4:A3:A2:A1:A0:RS]
      //
      // A zero in the R/S position of the first byte means that the master
      // transmits (sends) data to the selected slave, and a one in this position
      // means that the master receives data from the slave.
      //

      Suppose my device slave address in 0x39(given in the datasheet), do I need to append RS bit.? 
      My master is always in read mode.  

      slave address i2c
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • cb1_mobile
      Posted by cb1_mobile
      on Apr 26 2012 07:15 AM
      Guru21870 points

      Will answer with an example - our firm uses an I2C based GPIO expander which has the Slave Address 0x20.  StellarisWare function is coded as shown, below:

              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x20, false); // Config'd for write @ slave adr 0x20

      Your MCU may not have the in-built ROM functions - in that case use I2CMaster...

      What you call RS bit is R/W in I2C terminology - and is automatically placed for you by StellarisWare.  (via last entry w/in function - false = write, true = read)  Signal "RS" suggests that yours is an I2C-based Display - several of these have issues - suggest that you experiment & master I2C with the safer, more robust I2C EEprom.  Keep in mind that I2C accommodates 7 bit addressing - thus the Msb should never be set when placed/coded w/in the I2C address field.

      Curious if you reviewed earlier referenced I2C post - and if you found that useful?  (it was generated to assist those with exact I2C issues you presented...)

       

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • A Newbie
      Posted by A Newbie
      on Apr 26 2012 16:01 PM
      Prodigy150 points

      Hello, 

      I went through your first post. It really helped me in setting up the pin configurations. Thanks a lot. 

      But I'm trying to use I2C0 in read mode. My EVALBOT need to read data. I have used the above said function with true to put my slave address on bus. 

      I have the following issues. 

      • After running the program, when I see the I2C0Master registers, the busy bit is always set to 1. 
      • I need to read from specific registers of slave (reg 14 and 15). How do I specify that?
      • If I'm using evalbot always in master mode, should I use I2CSlaveEnable(I2C0_SLAVE_BASE) ? 
      • I'm using the following functions to read data. 

      I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);  //Dummy 1 byte receive

      while(!(I2CSlaveStatus(I2C0_SLAVE_BASE) & I2C_SLAVE_ACT_TREQ))
      {
      }

      ulDataRx = I2CMasterDataGet(I2C0_MASTER_BASE);

      It is always stuck in the while loop. 

      I know I'm doing something fundamentally wrong somewhere. Please help me identify my mistake(s). 

      i2c0 master read
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • A Newbie
      Posted by A Newbie
      on Apr 26 2012 19:48 PM
      Prodigy150 points

      Please have a look into my code. 


      void main(void)
      {
      ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //LEDS
      ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4 | GPIO_PIN_5);

      ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);

      GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_OD);
      GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_OD);
      GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_DIR_MODE_HW);
      GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_DIR_MODE_HW);


      I2CMasterEnable(I2C0_MASTER_BASE);
      I2CMasterInitExpClk(I2C0_MASTER_BASE,SysCtlClockGet(),true); //Initialises I2C Master
      //I2CSlaveInit(I2C0_SLAVE_BASE, 0x39); //Initialises I2C Slave
      //I2CSlaveEnable(I2C0_SLAVE_BASE);
      I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, 0x39,true);

      int i;
      int controlWord;
      controlWord = I2C_MASTER_CMD_BURST_RECEIVE_START;
      int numberOfBytes = 16;
      char* data;


      for(i = 0; i < numberOfBytes; i++)
      {
      // The second byte has to be receive with CONTINUE control word
      if(i == 1)
      controlWord = I2C_MASTER_CMD_BURST_RECEIVE_CONT;
      // The last byte has to be receive with FINISH control word
      if(i == numberOfBytes - 1)
      controlWord = I2C_MASTER_CMD_BURST_RECEIVE_FINISH;
      // If we have only one byte to receive, it is not BURST send but SINGLE
      if(numberOfBytes == 1)
      controlWord = I2C_MASTER_CMD_SINGLE_RECEIVE;

      // Read a byte
      I2CMasterControl(I2C0_MASTER_BASE, controlWord);
      // Wait to finish reading
      DCLK_status= I2CMasterLineStateGet(I2C0_MASTER_BASE); //2 bit status of SDA and SCL
      while(I2CMasterBusy(I2C0_MASTER_BASE));

      // Move byte from register
      data[i] = I2CMasterDataGet(I2C0_MASTER_BASE);
      }

      }

      My SDA and SCL is always 0, and Master I2c is always busy. 

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • cb1_mobile
      Posted by cb1_mobile
      on Apr 27 2012 09:03 AM
      Guru21870 points

      Pardonnez-moi - haven't time to go thru your code - maybe later upon landing.  Instead - here is known good code which reads from a TI - I2C-based ADC - by comparing listings you can likely discover a "fix."  Later - will try & review your code - as/if still required.  Again - this code runs on Stellaris M4F "'talking" to mini TI I2C-based ADC.

      *** Update: Unclear if you have - earlier - succeeded in generating an I2C Write (from Stellaris) to I2C Slave.  Thought that the reference posts covered that aspect well - before delving into your failed receive - have you tested your I2C WRITES?  As code below shows - any attempt @ I2C Read is doomed without earlier, successful I2C Writes.

      *** Update 2: Like this aspect of your I2C code:

      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);

      but then - your next few lines (below) "undo" your nice I2C set-up:   KILL these 4 lines (below):

      GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_OD);
      GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_OD);
      GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_DIR_MODE_HW);
      GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_DIR_MODE_HW);

      If interested - you can visit functions GPIOPinConfigure() and GPIOPinTypeI2C() and learn the detail of how they function - you "undo" much of their work with the code listed - urge you to kill.

      You really need to first positively establish that you can Write via I2C - using the sample code/set-up from reference post.  Please include your "Pass/Fail" I2C Write RESULTS  before we continue with I2C Read...  Even a basic scope can track/reveal SDA & SCL activity - do not forget pull-up Rs to 3V3.  (3-10K usually fine)

      Here - known good config: Stellaris M4F (yours may not require PinType listed - review datasheet)

      i2c_setup: 
         
              ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
         
              GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);   //   *** Note special I2CSCL treatment for M4
              ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);   
         
              ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);   
              ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);   

            while(1)
            {
             
              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, false); // Write  0x48 address Slave ADC
              ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x8); // Rd CH3 Upper byte w/in ADC
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
            // Delay until transmission completes
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE)) {}

              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, true); // Read  slave @ 0x48 
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE)) {}

              ulADCup = ROM_I2CMasterDataGet(I2C1_MASTER_BASE);   //  upper byte recovered into var ulADCup 
            
              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, false); // Write
              ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x09); // Rd CH3 Lower Byte
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE)) {}

              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, true); // Read       
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}

              ulADClo = ROM_I2CMasterDataGet(I2C1_MASTER_BASE);       //  lower byte recovered into var ulADClo
              
              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, false); // Write
              ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x01); // IntCtrl Reg
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE)) {}
           
              ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x48, true); // Read
              ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);        
              while(ROM_I2CMasterBusy(I2C1_MASTER_BASE)) {}
           
              ulINTCTRL = ROM_I2CMasterDataGet(I2C1_MASTER_BASE);             
             
              ulADC_count ++;
              ROM_SysCtlDelay(9000000);
            }

      Try this and report.  (should this work - kindly report & let's "wrap" this forum thread (expanding beyond listed Subject)  Also - like to know if use of color & bold assists your/others understanding and the "flow" of the post. 

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Greg Whitmore
      Posted by Greg Whitmore
      on Apr 30 2012 05:20 AM
      Expert1185 points

      I have I2C working properly on the evalbot. The software was derived using the display driver as a starting point. The OLED is operating on I2C1. Look at display96x16x1.c in \StellarisWare\boards\ek-evalbot\drivers. It will show you how to initialize the I2C channel and send commands to the OLED. After that, the reading is easy.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • A Newbie
      Posted by A Newbie
      on May 02 2012 02:52 AM
      Prodigy150 points

      Hello,  

      Thanks a lot for your elaborate reply. The color scheme and bold does assist very much in understanding the flow.

      PULL UP :

        

      Please not that I2C0 in Evalbot is connected to audio module with pull up of 1K. Do you want me to add more resistance?

      I tried writing to the slave. Was able to execute all statements in the CCS simulator. The ACK for data and address is 0(reset value), meaning acknowledged.  The MCS register doesn't exhibit any changes for second write nor for any reads. Also the bit in MCS corresponding to generate start and stop is always at zero.

      If i'm able to get a oscilloscope, I will share the observations. 

      I tried reading, but the value read is always zero which is wrong. Also, I need to read from a particular register in slave. How do it do that? 

      I2CMasterDataGet(I2C0_MASTER_BASE) : is this is the only way to read? 

      Thanks a lot for your time and effort. I really appreciate it. 

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • A Newbie
      Posted by A Newbie
      on May 02 2012 03:02 AM
      Prodigy150 points

      Hello Greg, 

      I studied the display96x16x1.c and other I2C example code. I have attached my code, please have a look it it if you get time. 

      6708.i2c.c

       

      The issue is that the value read is always zero. Any quick thought?

      -Thanks 

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • cb1_mobile
      Posted by cb1_mobile
      on May 02 2012 08:51 AM
      Verified Answer
      Verified by A Newbie
      Guru21870 points

      Not Greg but have "quick thought."  To read a particular I2C Slave's specific register you must match the Slave's set-up/config (primarily register address) protocol.  If I were you I'd temporarily use a very small EEprom (can just clip to your I2C bus - you will have to supply power) which greatly simplifies your read effort. 

      The I2CMasterDataGet() function usually is required to read from the slave (suggest you stay with this @ this stage)...   Until it is confirmed that your I2C "Writes" are proper - your Reads may continue to frustrate.  You may be able to find a free I2C data tester "on-line" - to confirm that your understanding & execution of I2C writes are correct.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use