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.

RM46L852: I2C communication - I need help with coding

Part Number: RM46L852
Other Parts Discussed in Thread: HALCOGEN

Hello!

I have question about working with I2C communication (code).

I was looking the example and I've tried to write my own code.


My slave address is 0x29 and before I can even go into reading I need to set up registers: ATIME, WTIME, ENABLE, CONTROL, CONFIG of the sensor (TCS34725).

So I've done this:

i2cSetSlaveAdd (i2cREG1, 0x29);
i2cSetDirection (i2cREG1, I2C_TRANSMITTER);

for (repeat = 0; repeat < 2; ++repeat) {
i2cSetCount (i2cREG1, 2);
i2cSetMode (i2cREG1, I2C_MASTER);
i2cSetStop (i2cREG1);
i2cSetStart (i2cREG1);
i2cSend (i2cREG1, 2, transmit_w_atime);

while (i2cIsBusBusy (i2cREG1))
;
while (!i2cIsStopDetected (i2cREG1))
;
i2cClearSCD (i2cREG1);
for (delay = 0; delay < 210; ++delay)
;
}

This is just a snippet. First time I am communicating to ATIME reg, next for loop I am communicating with WTIME and so on.

In this code I've sent transmit_w_atime [2]  =  { 0x01,   0xC0 } which are address of ATIME register and second one is what I want to write inside the ATIME register (is this the correct way to do it?)


Questions I additionally have:

  1. Is there faster way to send data in one go? To communicate with all five registers at once and send appropriate data to each one of them?
  2. Why do we use for (repeat = 0; repeat < 2; ++repeat) loop?
  3. When I want to read from a register, how do I specify in i2cReceive  () function the register from which I want to read from and in which variable to store my value?

Thanks!

Marc

  • Hello Marc,
    According to I2C protocols of TCS3472 device (figure 23 of device datasheet, downloaded from here: ams.com/.../TCS3472_DS000390_2-00.pdf ) and description of Command register you could set more than one register if registers are with consecutive addresses.
    You can send more than one byte using i2cSend(i2cBASE_t *i2c, uint32 length, uint8 * data) function. Prior to send bytes you should initialize data in proper order considering consecutive register addresses of slave device.
    You don't need for (repeat = 0; repeat < 2; ++repeat) loop. In that way you are sending data twice.
    I2C read is actually I2C write followed by I2C read. If a read command is issued, the register address from the previous command will be used for data access.

    Best regards,
    Miro
  • Miro,

    Thank you for your reply! :)

    I am not experienced with I2C communication and this is my project where I am trying to set it up, so would you mind if I've just asked to verify I understood you correctly? :)

    Before sending each packet I should write:

    i2cSetSlaveAdd (i2cREG1, SLAVE_ADDRESS);
    i2cSetDirection (i2cREG1, I2C_TRANSMITTER);

    or in case of receiving, I2C_RECEIVER in i2cSetDirection?

    Then, I use:
    i2cSetCount (i2cREG1, LENGTH);
    i2cSetMode (i2cREG1, I2C_MASTER);
    i2cSetStop (i2cREG1);
    i2cSetStart (i2cREG1);
    i2cSend (i2cREG1, LENGTH, SOME_ARRAY);

    This value length is how many data I have? So if I have ADDRESS_2_REG and VALUE_2_REG then I would write #define LENGTH 2, or in case I have address, data, address, data, address, data, I would write #define LENGTH 6, right?

    Is it possible to send to i2cSend function something like: i2cSend (i2cREG1, LENGTH, { value_1, value_2, ..., value_n }); without having to store them in SOME_ARRAY beforehand?

    Can you help me on how do I decide the value of for (delay = 0; delay < 1000; ++delay); loop for WAIT TIME? I am not sure how to do this, honestly.

    I was reading the same datasheet you've sent to me but from the figure 23 I thought that I need to send WRITE, READ, WRITE, READ, ... combination. So I can just do WRITE, WRITE, WRITE? Or READ, READ, READ?

    I am not sure I understood your explanation on receiving information, so can I try and use an example to see if I understood you correctly?

    When I write i2cReceive I would use SOME_ARRAY:

    i2cReceive (i2cREG1, 2, SOME_ARRAY);

    and that SOME_ARRAY is defined as { 0x16, read_red}?
    Do I send address of a register from where I want to read value as a first value and then a variable where I want that value to be stored as next?

    Reading red colour from this register is READ ONLY REGISTER, so I am not sure if this is the right way.

    Also, out of curiosity, in i2c example, there are:
    asm(" nop");
    asm(" nop");
    asm(" nop");
    instructions. What do they do? Do I need them? And how many and where?

    Sorry for troubling you with this. I am beginner and I want to understand how to work with I2C periphery (I do not have much knowledge about) because I want to implement some projects using TI HERCULES RM controllers.

    Thank you so much,
    Marc
  • Hello,
    To write data in registers you should do as follows:
    - you should issue i2c write (with appropriate slave address) followed by register address and 1 or more bytes of data;
    To read data you could do as follows:
    1. issue i2c read (with appropriate slave address). The receiver will re receive as much data as you point. The address of first register to read will be the last one you have used in previous operations.
    2. issue i2c write (with appropriate slave address) followed by register address. Then issue i2c read (with appropriate slave address). In this case first register that will be read is the one that follows i2c write.

    The following code writes 3 bytes:
    i2cSetSlaveAdd(i2cREG1,SLAVE_ADDRESS);
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
    i2cSetCount(i2cREG1, 3);
    i2cSetMode(i2cREG1, I2C_MASTER);
    i2cSetStop(i2cREG1);
    i2cSetStart(i2cREG1);
    i2cSend(i2cREG1, 3, Init_TX); //array with 3 bytes
    while(i2cIsBusBusy(i2cREG1) == true);
    while(i2cIsStopDetected(i2cREG1) == 0);
    i2cClearSCD(i2cREG1);

    If you want to use HALCoGen generated APIs the data must be in array.

    The following code will read 3 bytes:
    /* Configure address of Slave to talk to */
    i2cSetSlaveAdd(i2cREG1, SLAVE_ADDRESS);
    /* Set direction to Transmitter */
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
    /* Configure Data count */
    i2cSetCount(i2cREG1, 1);
    /* Set mode as Master */
    i2cSetMode(i2cREG1, I2C_MASTER);
    /* Set Stop after programmed Count */
    i2cSetStop(i2cREG1);
    /* Transmit Start Condition */
    i2cSetStart(i2cREG1);
    /* Tranmit number of data in Polling mode */
    i2cSendByte(i2cREG1, FIRST_REGISTER_TO_READ_ADDRESS);
    /* Wait until Bus Busy is cleared */
    while(i2cIsBusBusy(i2cREG1) == true);
    /* Wait until Stop is detected */
    while(i2cIsStopDetected(i2cREG1) == 0);
    /* Clear the Stop condition */
    i2cClearSCD(i2cREG1);

    while(i2cIsMasterReady(i2cREG1) != true);

    /* Set direction to receiver */
    i2cSetDirection(i2cREG1, I2C_RECEIVER);
    /* Configure Data count */
    i2cSetCount(i2cREG1, 3);
    /* Set mode as Master */
    i2cSetMode(i2cREG1, I2C_MASTER);
    /* Set Stop after programmed Count */
    i2cSetStop(i2cREG1);
    /* Transmit Start Condition */
    i2cSetStart(i2cREG1);

    /* Transmit number of data in Polling mode */
    i2cReceive(i2cREG1, 3 , (uint8 *)time);
    /* Wait until Bus Busy is cleared */
    while(i2cIsBusBusy(i2cREG1) == true);
    /* Wait until Stop is detected */
    while(i2cIsStopDetected(i2cREG1) == 0);
    /* Clear the Stop condition */
    i2cClearSCD(i2cREG1);

    while(i2cIsMasterReady(i2cREG1) != true);

    The following code is just to add delay. nop means "no opeartion".
    asm(" nop");

    Please, take a look at "example_i2c_pcf8570.c" under HALCoGen installation folder.

    Hope this helps.

    Best regards,
    Miro
  • Thanks, Miro!

    This helped! :)