• 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 » C2000™ Microcontrollers » C2000 32-bit Microcontrollers Forum » Always get NACK from I2C slave after sending the slave address from Concerto C28x core
Share
C2000™ Microcontrollers
  • Forums
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
C2000 Resources
  • Product Folder
  • C2000 Training Portal
  • C2000 Technical Training Catalog
  • C2000 Datasheets, App Notes, User Guides
  • C2000 Hardware Design Kits
  • controlSUITE for C2000 Software Library


  • InstaSPIN Resources
  • What is InstaSPIN?
  • Videos and Support


  • InstaSPIN-FOC and InstaSPIN-MOTION Resources
  • What is InstaSPIN-FOC?
  • What is InstaSPIN-MOTION?
  • Product Folder: F28069F, F28068F, F28062F, F28068M, F28069M
  • User’s Guide
  • Technical User’s Manual
  • Tools
  • Always get NACK from I2C slave after sending the slave address from Concerto C28x core

    Always get NACK from I2C slave after sending the slave address from Concerto C28x core

    This question is not answered
    Yuncheng Song
    Posted by Yuncheng Song
    on May 07 2012 16:05 PM
    Prodigy120 points

    Hello there,

    I have  a really annoy problem in using the I2C module in C28x core of a F28M35H52C device. After sending a start condition and the 7 bit slave address, and R/W bit, I always get a NACK signal from the slave. No matter how hard I tried. The I2C slave I am trying to use is a 3-axis accelerometer on an IMU board. I have proofed the I2C slave is working properly using another microcontroller. Thus, the problem must in the Concerto side, either code or hardware, or both.

    The pin 104 (GPIO32) for SDA, and pin 103 (GPIO33) for SCL, pull up both internally and externally.  Pullup condition has been checked by measuring the pin voltage right before running the C28x code. In addition, the waveform from a scope confirmed the SDA is high during the 9th SCL pulse. 

    I am very frustrated now. The following is my code based on the sample code with F28335. Any comments and advise will be highly appreciated. Thanks all.



    #include "F28M35x_Device.h"     // F28M35x Headerfile Include File
    #include "F28M35x_Examples.h"   // F28M35x Examples Include File
    #include "F28M35x_I2C.h"
    #include "C28x_FPU_FastRTS.h"
    #include "math.h"


    #define C28_FREQ    150         //CPU frequency in MHz
    #define ADXL345ADDR    0x53        //as designed for sparkfun 6dom imu

    struct I2CMSG *CurrentMsgPtr;                // Used in interrupts


    void   I2CA_Init(void)
    {

        EALLOW;

        GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1;   // Configure GPIO32 for SDAA operation pin 104
        GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;   // Configure GPIO33 for SCLA operation pin 103

        EDIS;

        I2caRegs.I2CSAR = 0x0053;        // Slave address - ADXL345

        I2caRegs.I2CPSC.all = 14;            // Prescaler - need 7-12 Mhz on module clk  150Mhz/15=  10Mhz
        I2caRegs.I2CCLKL = 10;            // NOTE: must be non zero
        I2caRegs.I2CCLKH = 5;            // NOTE: must be non zero
        I2caRegs.I2CIER.all = 0x24;        // Enable SCD & ARDY interrupts

        I2caRegs.I2CMDR.all = 0x0020;    // Take I2C out of reset
                                        // Stop I2C when suspended

        I2caRegs.I2CFFTX.all = 0x6000;    // Enable FIFO mode and TXFIFO
        I2caRegs.I2CFFRX.all = 0x2040;    // Enable RXFIFO, clear RXFFINT,
       return;

    }
    Uint16 I2CA_WriteData(struct I2CMSG *msg)
    {
       Uint16 i;

       // Wait until the STP bit is cleared from any previous master communication.
       // Clearing of this bit by the module is delayed until after the SCD bit is
       // set. If this bit is not checked prior to initiating a new message, the
       // I2C could get confused.
       if (I2caRegs.I2CMDR.bit.STP == 1)
       {
          return I2C_STP_NOT_READY_ERROR;
       }

       // Setup slave address
       I2caRegs.I2CSAR = msg->SlaveAddress;

       // Check if bus busy
       if (I2caRegs.I2CSTR.bit.BB == 1)
       {
          return I2C_BUS_BUSY_ERROR;
       }

       // Setup number of bytes to send
       // MsgBuffer + Address
       I2caRegs.I2CCNT = msg->NumOfBytes+1;

       // Setup data to send
       I2caRegs.I2CDXR = msg->MemoryLowAddr;
       for (i=0; i<msg->NumOfBytes; i++)
       {
          I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
       }

       // Send start as master transmitter
       I2caRegs.I2CMDR.all = 0x6E20;

       return I2C_SUCCESS;
    }

    interrupt void i2c_int1a_isr(void)     // I2C-A
    {
       Uint16 IntSource, i;

       // Read interrupt source
       IntSource = I2caRegs.I2CISRC.all;

       // Interrupt source = stop condition detected
       if(IntSource == I2C_SCD_ISRC)
       {
          // If completed message was writing data, reset msg to inactive state
          if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY)
          {
             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;
          }
          else
          {
             if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
             {
                CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
             }
             // If completed message was reading EEPROM data, reset msg to inactive state
             // and read data from FIFO.
             else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY)
             {
                CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;
                for(i=0; i < 1; i++)
                {
                  CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR;
                }
             }
          }
       }  // end of stop condition detected

       else if(IntSource == I2C_ARDY_ISRC)
       {
          if(I2caRegs.I2CSTR.bit.NACK == 1)
          {
             I2caRegs.I2CMDR.bit.STP = 1;
             I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
          }
          else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
          {
             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;
          }
       }  // end of register access ready

       else
       {
          // Generate some error due to invalid interrupt source
          asm("   ESTOP0");
       }

       // Enable future I2C (PIE Group 8) interrupts
       PieCtrlRegs.PIEACK.bit.ACK8 = 1;
    }

    struct I2CMSG ADXL345In;
    struct I2CMSG ADXL345Out;


    void main(void)
    {

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F28M35x_SysCtrl.c file.
        InitSysCtrl();

    // Step 2. Initialize GPIO:
    // This example function is found in the F28M35x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //    InitGpio(); // Skipped for this example
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
        DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F28M35x_PieCtrl.c file.
        InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
        IER = 0x0000;
        IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
        InitPieVectTable();

    // Reassign ISRs.

        EALLOW;    // This is needed to write to EALLOW protected registers
        PieVectTable.I2CINT1A = &i2c_int1a_isr;
        EDIS;

        CurrentMsgPtr = &ADXL345In;

        ADXL345Out.MsgStatus = I2C_MSGSTAT_SEND_WITHSTOP;
        ADXL345Out.MemoryLowAddr = 0x2c;
        ADXL345Out.NumOfBytes = 1;
        ADXL345Out.MsgBuffer[0] = 0x04;
        ADXL345Out.SlaveAddress = 0x53;

        I2CA_Init();

        PieCtrlRegs.PIEIER8.bit.INTx1 = 1;    //// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1

        IER |= M_INT8;

    // Enable global Interrupts and higher priority real-time debug events:
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM

        Uint16 Error;
    // Step 6. IDLE loop. Just sit and loop forever (optional):
        do
        {
            if(ADXL345Out.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)
            {
               Error = I2CA_WriteData(&ADXL345Out);
               // If communication is correctly initiated, set msg status to busy
               // and update CurrentMsgPtr for the interrupt service routine.
               // Otherwise, do nothing and try again next loop. Once message is
               // initiated, the I2C interrupts will handle the rest. Search for
               // i2c_int1a_isr in this file.
               if (Error == I2C_SUCCESS)
               {
                  CurrentMsgPtr = &ADXL345Out;
                  ADXL345Out.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
               }
            }  // end of write section
        }while (ADXL345Out.MsgStatus!=I2C_MSGSTAT_INACTIVE);

        for(;;)
        {
            //
            // TO DO
            //

        }

    }

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Vishal_Coelho
      Posted by Vishal_Coelho
      on May 07 2012 18:52 PM
      Expert5725 points

      Hi Yuncheng

      Based on what I read from the ADXL datasheet pin 12(ALT_ADDRESS) needs to be grounded to use the alternate address 0x53. Can you check that pin on the breakout to make sure its properly grounded at the board and at pin12 of the accelerometer?

      Yuncheng Song
      #define ADXL345ADDR    0x53        //as designed for sparkfun 6dom imu

      If not looks like you can revert to the primary address 0x1D

      Regards,

      Vishal

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Ning Sa
      Posted by Ning Sa
      on May 09 2012 09:56 AM
      Prodigy140 points

      hello Vishal,

      Thanks for you advise, I've checked the salve hardware by using another known working microcontroller and software, they worked perfectly.

      The problem has been solved by itself, sort of...

      I changed the I2C module to loop-back mode once, then it started working perfectly ever since, with the exactly the same piece of code.

      best,

      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