1
\$\begingroup\$

I have been working with I2C protocol to create some code for the RA8875 (see for I2C from page 67) using a Tiva board (TM4C123, I2C chapter from page 997), and I was able to paint in the display or writing text, but I am struggling when I want to read a value from a register.

For what I could read about I2C, I understand that the process should be as it follows:

  1. Send a write command, specifying the adress of the register
  2. Send a read command, so the board reads the data from the register

The code I use for I2C read is the following:

unsigned char lcd_read(unsigned char data,short I2C)
{
    unsigned char response;
    switch(I2C)
    {
        case I2C0:
        {
            while(I2C0_MCS_R&I2C_MCS_BUSBSY);
            I2C0_MSA_R |=0x0E;  //Specify the slave address of the touch screen and that the next operation is a write command
            I2C0_MDR_R=data;    // Register address
            I2C0_MCS_R=0x03;    // (START, RUN)
            if(I2C0_MCS_R&I2C_MCS_ERROR)    //Check the ERROR bit in the I2CMCS register to confirm the transmit was acknowledged.
            {

            }
            I2C0_MSA_R |=0x0F;  //Specify the slave address of the touch screen and that the next operation is a read
            I2C0_MCS_R=0x07;    // (STOP, START, RUN)
            while(I2C0_MCS_R&I2C_MCS_BUSBSY);   //Wait until the transmiI2Con completes by polling the I2CMCS register's BUSBstart_Y bit until it has been cleared.
            response = I2C0_MDR_R&0xFF;
            if(I2C0_MCS_R&I2C_MCS_ERROR)    //Check the ERROR bit in the I2CMCS register to confirm the transmit was acknowledged.
            {

            }
            break;
        }
    }
    return response;
}

Another thing that happened to me is that what I can see in the registers (I use Code Composer Studio for coding and debugging) do not correspond to the data obtained using a protocol analyzer (i.e. content of register I2C_MDR). Probably this could be a separate question but, what can be the reason of it?

Edit: The following images show how data is transmitted. The read data should be 0x81 instead of 0x00:

I2C write to register:

I2C write, step 1 I2C write, step 2

I2C read from register using the code above:

I2C read, step 1 I2C read, step 2

Thanks for your help.

\$\endgroup\$
  • \$\begingroup\$ Please describe how you have connected the SCL and SDA lines. What sort of pullup resistors are you using? Are there other devices on the bus? \$\endgroup\$ – Elliot Alderson Dec 1 '18 at 16:09
  • \$\begingroup\$ The steps where you "Specify the slave address of the master" don't make much sense to me. An I2C master does not have a slave address. You should be sending the address of the slave device you want to talk to out onto the bus. \$\endgroup\$ – brhans Dec 1 '18 at 16:19
  • \$\begingroup\$ @ElliotAlderson There is no other device on the bus, and the used pullup resistors are the ones already integrated in the touch screen board. \$\endgroup\$ – Javier Dec 2 '18 at 19:29
  • \$\begingroup\$ @brhans You are right in that, my comment on the code was wrong. The addresses specified were of the slave device, in this case the touch screen. \$\endgroup\$ – Javier Dec 2 '18 at 19:31
1
\$\begingroup\$

I have not used the TM4 chip you are calling out, however are you sure the code written is calling out the repeated start correctly?

Also, the probable cause, assuming the transaction is correct, Is you shouldn't be reading the I2C0_MDR_R register before you confirm the transaction completes. so move that line to just after your while(I2C0_MCS_R&I2C_MCS_BUSBSY);

\$\endgroup\$
1
\$\begingroup\$

I was reviewing my code and found the following mistakes:

  1. Slave address should not be set using an OR operation, so for example it should be I2C0_MSA_R = 0x0E instead of I2C0_MSA_R |= 0x0E

  2. The slave address for reading should be 0x0D instead of 0x0F

  3. The register must be read after the while as @robogeek78 suggested.

The following code is the valid one:

unsigned char lcd_read(unsigned char data,short I2C)
{
    unsigned char response;
    switch(I2C)
    {
        case I2C0:
        {
            while(I2C0_MCS_R&I2C_MCS_BUSBSY);
            I2C0_MSA_R=0x0E;  //Specify the slave address of the touch screen and that the next operation is a write command
            I2C0_MDR_R=data;    // Register address
            I2C0_MCS_R=0x03;    // (START, RUN)
            if(I2C0_MCS_R&I2C_MCS_ERROR)    //Check the ERROR bit in the I2CMCS register to confirm the transmit was acknowledged.
            {

            }
            I2C0_MSA_R=0x0D;  //Specify the slave address of the touch screen and that the next operation is a read
            I2C0_MCS_R=0x07;    // (STOP, START, RUN)
            while(I2C0_MCS_R&I2C_MCS_BUSBSY);   //Wait until the transmiI2Con completes by polling the I2CMCS register's BUSBstart_Y bit until it has been cleared.
            response = I2C0_MDR_R&0xFF;
            if(I2C0_MCS_R&I2C_MCS_ERROR)    //Check the ERROR bit in the I2CMCS register to confirm the transmit was acknowledged.
            {

            }
            break;
        }
    }
    return response;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.