This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

i2c write & ack polling for microchip 24LC1025

I use 4 EEPROMs of microchip 24LC1025 in 28335 i2c bus.

I use i2c tx & rx fifo interrupt (max 16 byte). the 24LC1025 memory is manged by page unit (of 128 byte size).

When I write into eeprom, all operation is ACKED.

I have a problem, which is the ACK Polling procedure.

ACK polling procedure is only that a write control byte for check ACKED.

How can I send only a write control byte?

the followings are my code part.:

// ---------------- Sending
    I2caRegs.I2CSAR = pMsg->slaveAddress;
    I2caRegs.I2CMDR.all = 0x6EA0;  // (RM=1, no FIFO data)

//---------------- In ISR i2c_int1a_Isr
if(IntSource ==I2C_ARDY_ISRC)
{
  // OK. Acked.
  // end of it.
}
if( IntSource == I2C_NACK_ISRC )
{
  if( I2caRegs.I2CSTR.bit.NACK == 1)
  {
    I2caRegs.I2CMDR.bit.STP = 1;
    I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    // NACKed.
    // re-try ACK polling
  }
}

//------------------- end of code -----------------------------

Cho, Cheol-Hyeon.

  • After writng, the ack polling wave form is follows.:

    <Legend: Green=SCL, Voilet=SDA>

    The wave form is sequence of START, Control code (1010000 + _W), and ack.

    The last bit is NACKed from slave device.

    In this case TI DSP28335 does not generate NACK interrupt but only generate ARDY interrupt.

    Is this a bug?

  • After sending "write command" is completed, "I2caRegs.I2CMDR.all = 0x6620;" sends a control byte.

    (In this condition, because the internal count is 0, after the 2C module sends CONTROL byte it generates the ARDY interrupt.)

    Why does not the I2C module detect NACK of CONTROL byte?

  • Finally,my code is,

    Uint16 i2cA_WriteAckPolling(i2c_message_t *pMsg)
    {
      Uint16 uRet = I2C_ERROR;
    
      // 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 (1 == I2caRegs.I2CMDR.bit.STP)
      {
        uRet = I2C_STP_NOT_READY_ERROR;
        return uRet;
      }
    
      // Check if bus busy
      #if 0
      if (1 == I2caRegs.I2CSTR.bit.BB)
      {
        uRet = I2C_BUS_BUSY_ERROR;
        return uRet;
      }
      #endif
    
      if( pMsg )
      {
        uRet = I2C_SUCCESS;
    
        // disable i2c module
        //I2caRegs.I2CMDR.bit.IRS = 0;
    
        // Setup slave address
        //I2caRegs.I2CSAR = pMsg->slaveAddress;
    
        pMsg->seq++;
    
        if( 1 != I2caRegs.I2CCNT )
        {
          I2caRegs.I2CCNT = 1;
          I2caRegs.I2CDXR = (pMsg->address >> 8) & 0xFF;
          //I2caRegs.I2CDXR = (pMsg->address & 0xFF);
        }
        I2caRegs.I2CMDR.all = 0x6620;
        // RM=0, Internal Count = 1.
    
        //i2ca_clear_tx_fifo_interrupt();
        //i2ca_enable_tx_fifo_interrupt();
    
      }
    
      return uRet;
    }
    
    void i2cA_Initialize(void)
    {
      //...
      I2caRegs.I2CIER.all = 0x26; // Enable SCD & ARDY, NACK interrupts
      //...
    }
    
    interrupt void i2c_int1a_Isr(void) // I2C-A
    {
      Uint16 IntSource;
    
      // Read interrupt source
      IntSource = I2caRegs.I2CISRC.all;
    
      // Interrupt source = stop condition detected
      if(IntSource == I2C_SCD_ISRC)
      {
        if( l_pI2cMessage )
        {
          // If completed message was writing data, reset msg to inactive state
          if (l_pI2cMessage->state == I2C_MSGSTAT_WRITE_BUSY)
          {
            // Write
            l_pI2cMessage->state = I2C_MSGSTAT_WRITE_XMITED;
            // write length is l_pI2cMessage->count.
          }
          else if (l_pI2cMessage->state == I2C_MSGSTAT_WRITE_ACKPOLLING)
          {
            // Ack polling result is ACKED. write END.
            l_pI2cMessage->state = I2C_MSGSTAT_WRITE_FINE;
            // write length is l_pI2cMessage->count.
          }
          else
          {
            //...
          }
        }
      }
      else if(IntSource == I2C_NACK_ISRC)
      {
        // do not check
        // if(I2caRegs.I2CSTR.bit.NACK == 1)
        I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    
        if( l_pI2cMessage )
        {
          if( l_pI2cMessage->state == I2C_MSGSTAT_WRITE_ACKPOLLING )
          {
            l_pI2cMessage->state = I2C_MSGSTAT_WRITE_WRITEACK;
          }
          else
          {
            I2caRegs.I2CMDR.bit.STP = 1;
          }
        }
        else
        {
          I2caRegs.I2CMDR.bit.STP = 1;
        }
      } // end of NACK
      else if(IntSource == I2C_ARDY_ISRC)
      {
        if( l_pI2cMessage )
        {
          if( l_pI2cMessage->state == I2C_MSGSTAT_SEND_NOSTOP_BUSY )
          {
            l_pI2cMessage->state = I2C_MSGSTAT_RESTART;
          }
          else if( l_pI2cMessage->state == I2C_MSGSTAT_WRITE_ACKPOLLING )
          {
            I2caRegs.I2CMDR.bit.STP = 1;
          }
        }
      } // end of register access ready
      else
      {
        // Generate some error due to invalid interrupt source
      }
    
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
    }
    

    In this code, the Ack polling is completely working...

    Is this the best solution?