[SAMD51] I2C configuration

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi ,

 

we are using I2C communication to access the external EEPROM in our SAMD51 development project. We need to perform simple read and write operation. We have configured the I2C section like below.

 

 

clock core : 40 Mhz

clock slow : 32.77 Mhz

Are we missed anything .Please check and confirm us .

 

Thanks in advance.

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

 

We are communicating SAMD51 (Master) and At24C16 EEPROM(Slave) using I2C. We have selected the standard/fast mode and set the bus clock speed as 100Khz.

 

 

We set the slave address using ASF4 API (set_slave_address). We are using io_read() and io_write() API to read/write into the slave address.Please find our code below. But we are reading 0xFF or 0x00 from slave for whatever the address we are writing.

---------------------------------------------------------------------------

   atmel_start_init();
    
    i2c_m_sync_get_io_descriptor(&I2C_0, &I2c_io);
    i2c_m_sync_enable(&I2C_0);
    i2c_m_sync_set_slaveaddr(&I2C_0, 0x50, I2C_M_SEVEN);
    
  
             DataBuff = 0xA0;
             io_write(I2c_io, &DataBuff , 1);  //Writing device address (upper 3 bits of 1 bit word address followed by 1010)
             
             DataBuff = 0x00;
             io_write(I2c_io,&DataBuff , 1);  //writing remaining 8 bits of 11 bit word address
             
             Data1 = 0x55;
             io_write(I2c_io, &Data1 , 1);     //writing data as 0x55
            

              delay_ms(5);                            //delay needed after write operation (refer datasheet)
             
          
             DataBuff = 0xA1;
             io_write(I2c_io, &DataBuff , 1);  //reading from current address so passing only device address by setting R/W bit as 1)
             io_read(I2c_io, &buf, 1);            //reading data from current address
   

----------------------------------------------------------------------------------------------------------------------------

 

Anyone please  check and provide your inputs. 

 

Thanks in advance

 

 

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's strange that you would use an external eeprom when there is "Smart EEPROM" in the  SAMD51 but  anyway from the user guide  (available when configuring the I2C in Atmel Start) I get that each io_write/io_read will have a start condition, send/receive 1 byte and then a stop condition:

The stop condition is automatically controlled by the driver if the I/O write and read functions are used, but can be manually controlled by using the i2c_m_sync_transfer function.

 

This is not what you need. There are functions that will work better in this case:

Often a master accesses different information in the slave by accessing different registers in the slave. This is done by first sending a message to the target slave containing the register address, followed by a repeated start condition (no stop condition between) ending with transferring register data. This scheme is supported by the i2c_m_sync_cmd_write and i2c_m_sync_cmd_read function, but limited to 8-bit register addresses.

your "command" should be the 8 lower address bits. 

Also, the slave address is supposed to contain the upper bits of the eeprom address, i.e., set this with  i2c_m_sync_set_slaveaddr , the 0xA0 and 0xA1 bytes should not be sent in the data (strange how you got this wrong since 0x50 is the proper 7 bit address that in 8 bits becomes 0xA0).

Also I don't expect you can read out what you just wrote like you try the test code, the address in the eeprom is auto incremented so you would read 0xff also if the write worked.

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lajon,

 

Thanks for your inputs.

 

We have used two separate io_write() functions for sending the lower 8 bit address and data. From your input ,we came to know each io_write() will have separate start,stop conditions. So now we have  modified our code like below as per Figure 7-1. Byte Write in slave data sheet.

 

uint8_t Data1[2] = {0x00,0x55};

 

 io_write(I2c_io,Data1 , 2); //passing address and data in single io_write.

 

>>>>Also I don't expect you can read out what you just wrote like you try the test code, the address in the eeprom is auto incremented so you would read 0xff also if the write worked.

 

Even if we are using random read method,by referring Figure 8-2. Random Read section. But still we are reading 0xFF from slave. can you help us on this.

 

Could you please tell us how can we verify the bus clock speed is sufficient and baud rate value for the I2C?.because we are having doubt on our configuration part also.

 

Thanks in advance.

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your multi byte io_write should work for writing but for random read (where there is need to send an address and then read) you will have to use i2c_m_sync_cmd_read, did you try that?

I can't imagine there would be a problem with the clock speed but you should really have some tool to look at the signals (e.g., a cheap USB logic analyzer with protocol decode). What pull up resistor value are you using?

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lajon,

 

Thanks for your inputs.

 

>>>Your multi byte io_write should work for writing but for random read (where there is need to send an address and then read) you will have to use i2c_m_sync_cmd_read, did you try that?

 

We have used io_write() with multi bytes for write operation. For read operation we ahve used i2c_m_sync_cmd_read() .Now we are able to perform the read operation form the specified address. But we are able to send only 8 bit address. If the address is more than 8 bits means how can we write the address into slave. Because AT24C16 has 11 bit word address.

 

Thanks in advance.

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, the slave address is supposed to contain the upper bits of the eeprom address, i.e., set this with  i2c_m_sync_set_slaveaddr

Did you try this already and it does not work or what?

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lajon,

 

            i2c_m_sync_set_slaveaddr(&I2C_0, 0x50, I2C_M_SEVEN);        // slave address = 0x50 because  upper 3 bits we have set as 000  (11 bit address 000 1111 1111)
             i2c_m_sync_cmd_read(&I2C_0, &Reg_address, &buf,  1);         // Reg_address = 0xFF (lower 8 bit address)

 

We are able to read the data successfully from slave up to 0xFF address without any issues.using above code.

 

But if we are setting the upper 3 bits for read/write operation we are reading 0x00 from the slave.We are unable to access the address which has been more than 8 bit address.

 For example:          

             i2c_m_sync_set_slaveaddr(&I2C_0, 0x51, I2C_M_SEVEN);        // slave address = 0x51 because  upper 3 bits we have set as 001  (11 bit address 001 0000 0000)
             i2c_m_sync_cmd_read(&I2C_0, &Reg_address, &buf,  1);         // Reg_address = 0x00 (lower 8 bit address)

kindly check this.

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is that really the code you have calling i2c_m_sync_cmd_read? You should get a warning from that 2:nd argument because it should be the command not the address of the command (Reg_address not &Reg_address).

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lajon,

sorry for the inconvenience.

We are not using any variable for register address. For representation we have used the name.

Please find our actual code below.

 

 i2c_m_sync_cmd_read(&I2C_0, 0xFF, &buf,  1);

 

thanks

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the read successful (returns 0)?

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes ,the call is successful.(API is returning 0)

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

call is successful.While using 0x50 as slave address.

But when we are using 0x51 ,the call is not successful.

 

Thanks

Karthi

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it possible you are trying to read too soon after the write? But I don't know why there would be a difference depending on the address. You should really get some tool and look at the I2C signals (or send me a At24C16 and I can have a look :-)

/Lars