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.

interfacing 24LC128 with MSP430

Hi all,

I successfully interfaced 24LC16 eeprom to MSP4302417 controller and the same code works for 24LC128 also but it only writes on first page 0x50 not above 0x51 etc can anyone tell me solution for this

EEPROMWRITE 24LC16

void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned char WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
{
 int i;    
             
          UCB0I2CSA = BlockAdd; 
          UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                 while((IFG2&0x08)==0x00);
            for (i=0;i<10;i++); 
        for (i=0;i<10;i++);       //delay
 UCB0TXBUF = WriteAddr;      //0x00;
              while(UCB0CTL1&UCTXSTT);                    //Send the start condition
              while((IFG2&0x08)==0x00); 
             for(i=0;i<NumByteToWrite;i++)
 {
  UCB0TXBUF = *ee_buffer;
  ee_buffer++;
  while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
 } 
 
 UCB0CTL1 |= UCTXSTP;
 
 while(UCB0CTL1&UCTXSTP);                    //Send the start condition
 
 for (i=0;i<10000;i++);      //delay

 


}

EEPROM READ 24LC16

 

void I2C_EE_BufferRead(unsigned char* ee_buffer, unsigned char ReadAddr, unsigned int NumByteToRead, unsigned int BlockAdd)

 int i;   
   
       
        UCB0I2CSA = BlockAdd;
 UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
 while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
    
       for (i=0;i<10;i++);       //delay
 UCB0TXBUF = ReadAddr;
 while(UCB0CTL1&UCTXSTT);                    //Send the start condition
 while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
       
       UCB0TXBUF = 0x00;
 //while(UCB0CTL1&UCTXSTT);                    //Send the start condition
 while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
       
       
       
 UCB0CTL1 &= ~UCTR;       //0xEF;//make it reciver
 UCB0CTL1 |= UCTXSTT;                   // I2C TX, start condition
 while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
        for (i=0;i<10;i++);
 while(UCB0CTL1&UCTXSTT);                    //Send the start condition
 for(i=0;i<(NumByteToRead-1);i++)
 {
  while((IFG2&0x04)==0x00);                      //check IFG2 for transmit interrupt flag
  *ee_buffer = UCB0RXBUF;
  ee_buffer++;
 } 
 UCB0CTL1 |= UCTXSTP;
 while((IFG2&0x04)==0x00);                      //check IFG2 for transmit interrupt flag
 *ee_buffer = UCB0RXBUF;
 while(UCB0CTL1&UCTXSTP);                    //Send the start condition 

 

 

 

 

 

 

  • Hi rupesh,

    do you know that TI has a I2C Master (and also a Slave) application note? You can find it here http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=slaa382 .

    Rgds
    aBUGSworstnightmare 

  • this library is useless even TI people told me the code i posted is working i just want to know how to pass high address byte and low address byte  in 24LC128

  • Hi rupesh,

    even if the library is useless from your point of view, a look at a 24LC128 data sheet wouldn't *g*!

    The sequence for doing a Page Write on a 24LC128 is:

    START-COMMAND BYTE -> ACK ->ADDRESS HIGH BYTE-> ACK ->ADDRESS LOW BYTE-> ACK -> DATA BYTE0-> ACK -> ... DATA BYTE63-> ACK -> STOP. Also refer to the picture below:

     

    Pls note: Page write operations are limited to writing bytes within a single physical page, regardless of the number of bytes actually being written. Physical page boundaries start at addresses that are integer multiples of the page buffer size (or ‘page size’) and end at addresses that are integer multiples of [page size – 1]. If a Page Write command attempts to write across a physical page boundary, the result is that the data wraps around to the beginning of the current page (over- writing data previously stored there), instead of being written to the next page, as might be expected. It is, therefore, necessary for the application software to prevent page write operations that would attempt to cross a page boundary.

    Rgds
    aBUGSworstnightmare 

  • please see the above sample code posted in that code I have done the same thing . the code only writes on 0x50

    rupesh

  • Hi rupesh,

    I'm sorry, but I only see you sending the Write-Address 'unsigned char WriteAddr' (UCB0TXBUF = WriteAddr;) to the slave which has the device-address 'unsigned int BlockAdd' (UCB0I2CSA = BlockAdd;).

    So, you only send one address byte to the slave and not two as needed.

    Rgds
    aBUGSworstnightmare 

  • hi this is the code to write on 24LC128 will this work?

    void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned char WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
    {
     int i;   
           //Block Address
                UCB0I2CSA = BlockAdd>>8; 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
           
                //Block Address
                UCB0I2CSA = BlockAdd&0xFF; 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
           

                for (i=0;i<10;i++); 
                UCB0TXBUF = WriteAddr;      //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
               for(i=0;i<NumByteToWrite;i++)
         {
      UCB0TXBUF = *ee_buffer;
      ee_buffer++;
      while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
         } 
     
         UCB0CTL1 |= UCTXSTP;
     
         while(UCB0CTL1&UCTXSTP);                    //Send the start condition
     
         for (i=0;i<10000;i++);      //delay
    }

    regards

    rupesh

  • Hi Rupesh,

     

    The code you have posted above will not work, since you are changing the I2C slave address to which the MSP is trying to send. UCB0I2CSA is the slave address to which the I2C Master inside the MSP is trying to communicate. If you are talking to just a single I2C slave in your application it can be configured once and not changed again.

    The base issue is that 24LC128 has 16K bytes, which means it will require 14-bits of address. This requires more than 1 byte. In your code you have declared WriteAddr as unsigned char, restricting it to 8-bits. Hence WriteAddr alone cannot access the whole EEPROM.

    Actually I am unable to understand what BlockAdd and WriteAddr are being used for. Is BlockAdd the page address and WriteAddr the actual address inside the page in which to write ? For example if you want to write from the 7 byte on page 10, will BlockAdd =10 and WriteAddr = 7 ?

    If this is the case, then you will need to calculate your 14-bit address using BlockAdd and WriteAddr:

    unsigned int StartAddr = ((BlockAdd * PAGE_SIZE) + WriteAddr) & 0x3FFF; // Restrict to 14-bits...

    Next you need to send this 14-bit address, high byte first. This needs to be send using UCB0TXBUF and NOT UCB0I2CSA.

    // First send Start....

    UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);

    UCB0TXBUF = (StartAddr) >> 8;

    // Wait for it to be sent..

    while((IFG2&0x08)==0x00);

    UCB0TXBUF = (StartAddr) ;

    // Wait for it to be sent..

    while((IFG2&0x08)==0x00);

    By sending START, you are sending the slave address, followed by the two address bytes. Next you can start writing your data bytes.

    Regards,

    Praval

  • Rupesh,

    A few thoughts...

    (1)

    Are you trying to do a page write or multiple byte writes?

    If you are attempting to do a page write you must take care of the page boundaries in software. If the page boundaries are not adhered to then the page simply gets over- written instead of automatically rolling over to the next page.

    For example; if the current page '1' has a page size = 'N' and the length of the string to be written is N+2, the first two bytes of page A get over written instead of rolling over to page B. User software has to ensure that at size N a new I2C transaction is started with the next page address.

    (2)

    If you have a screen shot that shows the failed transaction it may help. Does reading from 0x51 return incorrect bytes or does it mot work at all? How did you verify that this page is not being written?

    (3)

    In the EEPROM_Read function, first an address byte is transmitted, followed by a restart condition and then bytes are read out.

    Any reason for checking the transmit flag in the read portion of the code?

    UCB0CTL1 &= ~UCTR;       //0xEF;//make it reciver
     UCB0CTL1 |= UCTXSTT;                   // I2C TX, start condition
     while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag --> Checks for UCB0TXIFG?
            for (i=0;i<10;i++);
     while(UCB0CTL1&UCTXSTT);                    //Send the start condition

    (4)

    rupesh vishwakarma said:
    this library is useless even TI people told me the code i posted is working

    The Master and Slave I2C USCI App reports aim to help users get started quickly on development, for any custom application the code provided will need to be modified/customized as required. However if you have any feedback on how we could improve these  application reports or code example you feel can be added please let us know.

    Regards,

    Priya

     

  • hi ,

    this is the code on which I am working it ia originally working with 24LC16 .we have 0x50 to 0x57 block address of 24LC16 and this code we provide

    unsigned char* ee_buffer= buffer which has to be written like     unsigned char Write_array[]="0123456789bcdefghijklmnopqrstuvwxyz";

    unsigned int BlockAdd =address of block which has to be written varries from 0x50 to 0x57

    unsigned char NumByteToWrite how many bytes to write

    unsigned char WriteAddr 0n given block on which page has to be written like if we have to write on block 50 page 0 then block address is 0x50, page address is 0x00


    void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned char WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
    {
     int i;   
           //Block Address
                UCB0I2CSA = BlockAdd; 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++); 
                UCB0TXBUF =  WriteAddr ;      //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
               for(i=0;i<NumByteToWrite;i++)
         {
      UCB0TXBUF = *ee_buffer;
      ee_buffer++;
      while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
         } 
     
         UCB0CTL1 |= UCTXSTP;
     
         while(UCB0CTL1&UCTXSTP);                    //Send the start condition
     
         for (i=0;i<10000;i++);      //delay

    }

    This code works good for any block address 0x50 to 0x57 in case 24LC16

    now in case of 24LC128 when the block address is 0x50 page address 0x00 it works fine
    now suppose I want to write on block 0x51 with page address 0x00 then it does not work
    I tied to modify inthis manner

    void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned char WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
    {
     int i;   
           //Block Address
                UCB0I2CSA = BlockAdd>>8;//hi address 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++); 
         UCB0I2CSA = BlockAdd&0xFF;//low address 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++); 
                UCB0TXBUF =  WriteAddr ;      //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
               for(i=0;i<NumByteToWrite;i++)
         {
      UCB0TXBUF = *ee_buffer;
      ee_buffer++;
      while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
         } 
     
         UCB0CTL1 |= UCTXSTP;
     
         while(UCB0CTL1&UCTXSTP);                    //Send the start condition
     
         for (i=0;i<10000;i++);      //delay

    }


    is the above method correct to pass hi address and low address?
    if yes then also this is not working

    then what I did as the following as given in the post

    void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned char WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
    {
         int i,start_address;   
                start_address=((BlockAdd * 64) + WriteAddr) & 0x3FFF;     //Block Address
                UCB0I2CSA = BlockAdd; 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++); 
                UCB0TXBUF = (start_address)>>8;      //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
                 UCB0TXBUF =  start_address ;      //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
               for(i=0;i<NumByteToWrite;i++)
         {
      UCB0TXBUF = *ee_buffer;
      ee_buffer++;
      while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
         } 
     
         UCB0CTL1 |= UCTXSTP;
     
         while(UCB0CTL1&UCTXSTP);                    //Send the start condition
     
         for (i=0;i<10000;i++);      //delay
    }


    This case also does not work with 24LC128 with block address 0x51

    regards

    rupesh

  • Hi,

    Did you have 8 24LC16 in the original set up, which you are replacing with one 24LC128 ? In your original code you send I2C slave address from 0x50 to 0x57 and all of them work. This means you have 8 slaves with I2C addresses from 0x50 to 0x57. 

    Regards,

    Praval

  • Hi rupesh,

    could you please answer one simple question: Do you have more than one I2C slaves or not?

    If yes, what is BlockAdd?? Is it the address of your I2C slave or not (i.e. first device (slave) is at 0x50, second device (slave) is at 0x51, ..)??

    UCB0I2CSA holds the address of the I2C slave to be addressed, so if you only have one slave connected to the bus it must only be written once since the slave address doesn't change during application run time. If you have more than one then you need to change it.

    Further below in your latest post you're talking of page address 0x00. So, is this the number of the page (page size is 64bytes) you want to write to (i.e. if you want to write the 70th byte in the EEPROM which is located on page 1 then your page address is 0x01)? If so, you need to send this address to the EEPROM (as pointed out above) and not add it to your device address.

    Rgds
    aBUGSworstnightmare 

    P.S. Here is the link to the I2C-Bus specification http://www.nxp.com/acrobat_download2/literature/9398/39340011.pdf. Put it to good use!

  • hi,

    no I have only one 24LC16 , actually in my application i have to write different data on different locations of 24LC16  it has address range from 0x50 to 0x57 .actually it has 8 blocks on which we cam write data that is what I am passing it  as slave address

    rupesh

  • Hi,

    Just checked the 24LC16 datasheet. There is difference in the way 24LC16 and 24LC128 are organized due to which the code is not working properly. 24LC16 is of size 2048 bytes, which means it will need 11 address bits. It is organized in 8 blocks of 256 bytes each. The blocks are addressed by three bits of the slave address. Due to this you can support only a single 24LC16 in a system and your slave address can vary from 0x50-0x57, in which the Block address varies from 0 to 7. Your WriteAddr can vary from 0-255 which is the size of the Block. However 24Lc128 does not have this Block based architecture. It responds just to Slave address 0x50. Hence you cannot directly map BlockAddr to Slave address as was being done in 24LC16 code. You will need to set Slave Address to 0x50 always, irrespective of BlockAddr. You can use BlockAddr and WriteAddr to create an address which needs to be sent to 24LC128 as follows:

    int StartAddr = (BlockAddr - 0x50) * 256 + WriteAddr;


    You will notice that StartAddr varies from 0-255 depending on WriteAddr for BlockAddr = 0x50. For the next BlockAddr of 0x51 is starts at 256.

    Suggested Code that should work:

             int i,start_address;  
                start_address=(((BlockAdd - 0x50) * 256) + WriteAddr) & 0x3FFF;     //Start Address based on block

    address & Write Addr...
                UCB0I2CSA = 0x50;    // This needs to be 0x50 always....!!
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++);
                UCB0TXBUF = (start_address)>>8;      //0x00;
                for (i=0;i<10;i++);
                while((IFG2&0x08)==0x00);
                 UCB0TXBUF =  start_address ;      //0x00;
                for (i=0;i<10;i++);
                while((IFG2&0x08)==0x00);
     
    You should make similar changes in the EEPROM read code as well, making sure that Slave address (UCB0I2CSA) always remains 0x50. Since 24LC128 is of size 16384 bytes, it means it can have 64 blocks of 256 bytes. Hence your BlockAddr can go from 0x50 to 0x8F.

    A couple of things to note:
    a) NumByteToWrite should not exceed 64. Page write in 24LC128 is restricted to 64 bytes and is NumByteToWrite exceeds this, previous data will be overwritten and effectively only 64 bytes will be written.

    b) In 24Lc128 Page Write only the lower 6 bits of the address are incremented. The top 8 bits are not effected by Page Write. What this means is that Page Write does not cross page boundaries. For example if you set WriteAddr to 60 and NumByteToWrite to 10 then the write will be at addresses 60,61,62,63,0,1,2,3,4,5 and not on 60-69. This is because when you reach 64 and take only the lower 6 bits, you are left with just 0. Since the top 8 bits are not changed. Therefore your code should make sure you do not cross page boundaries while Page Write. Similar thing will happen if you set WriteAddr = 120 and write 10 bytes. They will be written at 120, 121, 122, 123, 124, 125, 126, 127, 64, 65.

    Hope this helps.

    Regards,

    Praval

  • Dear praval

    thanks very much to take the attention that 24LC128 is not block addressed and with your help the code is finally working thanks a lot once again

    here is the working code of 24LC128

    void I2C_EE_PageWrite(unsigned char* ee_buffer, unsigned int WriteAddr, unsigned char NumByteToWrite, unsigned int BlockAdd)
    {
         int i,start_address;
                start_address=(((BlockAdd - 0x50) * 256) + WriteAddr) & 0x3FFF; 
                UCB0I2CSA = 0x50; 
                UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
                while((IFG2&0x08)==0x00);
                for (i=0;i<10;i++); 
                UCB0TXBUF = (start_address)>>8;     //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
          
                UCB0TXBUF = start_address;     //0x00;
                for (i=0;i<10;i++); 
                while((IFG2&0x08)==0x00);
                 for(i=0;i<NumByteToWrite;i++)
         {
      UCB0TXBUF = *ee_buffer;
      ee_buffer++;
      while((IFG2&0x08)==0x00);               //check IFG2 for transmit interrupt flag
         } 
     
         UCB0CTL1 |= UCTXSTP;
     
         while(UCB0CTL1&UCTXSTP);                    //Send the start condition
     
         for (i=0;i<10000;i++);      //delay

    }


    void I2C_EE_BufferRead(unsigned char* ee_buffer, unsigned char ReadAddr, unsigned int NumByteToRead, unsigned int BlockAdd)

     int i,start_address;   
       UCB0I2CSA = 0x50;
            start_address=(((BlockAdd - 0x50) * 256) + ReadAddr) & 0x3FFF; 
     UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
     while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
           
           for (i=0;i<10;i++);       //delay
     UCB0TXBUF =  (start_address)>>8;
     while(UCB0CTL1&UCTXSTT);                    //Send the start condition
     while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
            UCB0TXBUF = start_address;
     while(UCB0CTL1&UCTXSTT);                    //Send the start condition
     while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
           
     UCB0CTL1 &= ~UCTR;       //0xEF;//make it reciver
     UCB0CTL1 |= UCTXSTT;                   // I2C TX, start condition
     while((IFG2&0x08)==0x00);                   //check IFG2 for transmit interrupt flag
            for (i=0;i<10;i++);
     while(UCB0CTL1&UCTXSTT);                    //Send the start condition
     for(i=0;i<(NumByteToRead-1);i++)
     {
      while((IFG2&0x04)==0x00);                      //check IFG2 for transmit interrupt flag
      *ee_buffer = UCB0RXBUF;
      ee_buffer++;
     } 
     UCB0CTL1 |= UCTXSTP;
     while((IFG2&0x04)==0x00);                      //check IFG2 for transmit interrupt flag
     *ee_buffer = UCB0RXBUF;
     while(UCB0CTL1&UCTXSTP);                    //Send the start condition 


    thanks a lot

    regards

    rupesh

  • Hi Rupesh,

    Glad I could help. Have you tried to read and write across the whole EEPROM, full 16384 bytes, to see everything is in ok ? As I mentioned you can go beyond the 0x57 Block Address, since this a larger EEPROM.

    Regards,

    Praval

**Attention** This is a public forum