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.

CC2538: CC2538 i2C eeprom 24lc16b

Part Number: CC2538


Hi everyone! I'm working with CC2538 as i2c master and have a problem with reading bytes from eeprom 24lc16b. This eeprom always responds 0xFF and I don't know why. There are two pull-up resistors 2.5k - on SDA and SCL pins. I attached three oscilloscopes diagrams: first is on writing byte 0x1, second - on sending eeprom address before reading (the same) and third - on reading. My code is here:

    //
    //  The I2C peripheral must be enabled before use.
    //
    SysCtrlPeripheralEnable(SYS_CTRL_PERIPH_I2C);

    //
    // Configure I2C pins
    //
    GPIODirModeSet(GPIO_I2C_BASE, PIN_I2C_SCL, GPIO_DIR_MODE_HW); 
    GPIOPinTypeI2C(GPIO_I2C_BASE, PIN_I2C_SCL);
    GPIODirModeSet(GPIO_I2C_BASE, PIN_I2C_SDA, GPIO_DIR_MODE_HW); 
    GPIOPinTypeI2C(GPIO_I2C_BASE, PIN_I2C_SDA);
    //
    // Configure pins as peripheral input and output
    //
    IOCPinConfigPeriphInput(GPIO_I2C_BASE, PIN_I2C_SCL, 
                            IOC_I2CMSSCL);
    IOCPinConfigPeriphInput(GPIO_I2C_BASE, PIN_I2C_SDA,
                            IOC_I2CMSSDA);    
    IOCPinConfigPeriphOutput(GPIO_I2C_BASE, PIN_I2C_SCL,
                             IOC_MUX_OUT_SEL_I2C_CMSSCL);
    IOCPinConfigPeriphOutput(GPIO_I2C_BASE, PIN_I2C_SDA,
                             IOC_MUX_OUT_SEL_I2C_CMSSDA);    

    //
    // Enable and initialize the I2C master module.  Use the system clock for
    // the I2C module.  The last parameter sets the I2C data transfer rate.
    // If false the data rate is set to 100kbps and if true the data rate will
    // be set to 400kbps.  For this example we will use a data rate of 100kbps.
    //
    I2CMasterInitExpClk(SysCtrlClockGet(), false);

#define	I2C_ADDR_24LC16		    (0xA0UL)	

    i2c_addr = (DWORD)((I2C_ADDR_24LC16 & 0xF0)>>1);

    //writing
    //eeprom address + memory block address. Last param means writing
    I2CMasterSlaveAddrSet(i2c_addr|0x1, false);  
    //put a byte 0x1 to DR register
    I2CMasterDataPut(0x1); 
    //send eeprom address, memory block address and a byte
    I2CMasterControl(I2C_MASTER_CMD_SINGLE_SEND);
    //wait until done
    while(I2CMasterBusy());          

    //reading
    //eeprom address + memory block address. Last param means writing
    I2CMasterSlaveAddrSet(i2c_addr|0x1, false);  
    //send eeprom address and memory block address
    I2CMasterControl(I2C_MASTER_CMD_SINGLE_SEND);
    //eeprom address + memory block address. Last param means reading
    I2CMasterSlaveAddrSet(i2c_addr|0x1, true);  
    //send eeprom address and memory block address
    I2CMasterControl(I2C_MASTER_CMD_SINGLE_SEND);
    //read byte from DR register
    uint32_t ans = I2CMasterDataGet();
    //wait until done
    while(I2CMasterBusy());    

Writing:

Sending address:


Reading:

Please, help somebody to solve this problem.


  • Addition:
    When I write byte 0x2 instead of 0x1 - reading is correct (0x2). And when I write bytes 0x2, 0x202, 0x302,...,0x802 I read only the lowest part - 0x2. After writing all other bytes I read 0xFF.
  • After several days of understanding how it must work I finally found a solution. Here is the code:

    #define	I2C_ADDR_24LC16		    (0xA0UL)	
    
    //Writing a block of 16 bytes: 
    
     unsigned char addr_hi;
     unsigned char txbuf[17];
     DWORD i2c_addr;
    
     // Determine an address
      addr_hi = (unsigned char)((addr >> 8) & 0x07);    //addr is the address of the block in eeprom
      // The lowest part of the address sends into the message
      txbuf[0] = (unsigned char)(addr & 0xFF);
      //Preparation of data
      for (DWORD i=0; i<count; i++)
      { 
        txbuf[i+1] = i;
      };
      i2c_addr = (DWORD)(((I2C_ADDR_24LC16 & 0xF0) | (addr_hi << 1))>>1);
    
      I2CMasterSlaveAddrSet(i2c_addr, false);  
      I2CMasterDataPut(txbuf[0]); 
      I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_START);
      //wait until done
      while(I2CMasterBusy());   
      while(I2CMasterErr()); 
      if (count>0)      //count is the count of bytes (=16)
      {
        for (int i=1; i<count; i++)
        {
          I2CMasterDataPut(txbuf[i]); 
          I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_CONT);
          //wait until done
          while(I2CMasterBusy());   
          while(I2CMasterErr());                            // Check the ERROR bit in the I2CM_STAT
        }  
        I2CMasterDataPut(txbuf[count]); 
        I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_FINISH);
        //wait until done
        while(I2CMasterBusy());   
        while(I2CMasterErr());                            // Check the ERROR bit in the I2CM_STAT
      }  
    
    
    //Reading a block of 16 bytes: 
    
      unsigned char addr_hi;
      DWORD i2c_addr;
    
      addr_hi = (unsigned char)((addr >> 8) & 0x07);  
      i2c_addr = (DWORD)((I2C_ADDR_24LC16 & 0xF0) | (addr_hi << 1));
    
      I2CMasterSlaveAddrSet(i2c_addr>>1, true); 
      I2CMasterControl(I2C_MASTER_CMD_BURST_RECEIVE_START);   //Start receiving data
      while(I2CMasterBusy());   
      while(I2CMasterErr());                            // Check the ERROR bit in the I2CM_STAT
      for (int i=0; i<count; i++)
      {
        ((uint8_t*)data)[i] = I2CMasterDataGet();    //read byte from DR register
        I2CMasterControl(I2C_MASTER_CMD_BURST_RECEIVE_CONT);
        //wait until done
        while(I2CMasterBusy());   
        while(I2CMasterErr());                            // Check the ERROR bit in the I2CM_STAT       
      }  
      I2CMasterControl(I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
      //wait until done
      while(I2CMasterBusy());   
      while(I2CMasterErr());  
    
    
    
    I hope it will helps somebody.