• Not Answered

TCA9548A: i2c multiplexing problem

Part Number: TCA9548A

I´m using a TCA9548A for multiplexing i2c devices with the same adress.
this i2c devices are bq3060 IC, and the objective is to read the registers from the ICs conected in port 0 and 1.
I managed to read the IC in port 0. Also the other IC in port 1. But when I try to read both ports, first port 0 and after port 1, some times I have reading problems. The problem is when there is a port selection change in the TCA.
I have seen that when I have reading problem is because in the i2c signal sent to select the port in the TAC9548 (in "tcaselect()" , "BP_WriteReg" ) the stop bit is not send correctly. I post below the code of my application and also I attached the i2c signal when I write the port of the TCA.
My question is, why can be that sometimes, when I write in TCA9548 the stop bit is not send correctly and other times yes. When it is not send ok, it seems that the clock signal is going down just when the data is going high for the STOP bit.

i2c signal sent to TCA in order to select the port (the black marked bit is the stop bit):


My code is the next:

  tcaselect(0); 
  VoltageArray[0]=BP_ReadReg(0x09);
  SOCArray[0]=BP_ReadReg(0x0d);  
 
  tcaselect(1); 
  VoltageArray[1]=BP_ReadReg(0x09);
  SOCArray[1]=BP_ReadReg(0x0d);

void tcaselect(uint8_t i) 
{
  if (i > 7) return; 
  tmp=(1<<i);
  BP_WriteReg(0x01,tmp); 
}

void BP_WriteReg(uint8_t RegName, uint8_t RegValue)
{
  /*-------------------------------- Transmission Phase -----------------------*/
  /* Send BP_I2C START condition */
  I2C_GenerateSTART(BP_I2C, ENABLE);

  /* Test on BP_I2C EV5 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_MODE_SELECT))  /* EV5 */
  {
  }

  /* Send BP slave address for write */
  I2C_Send7bitAddress(BP_I2C, i2c_MULT_ADDR, I2C_Direction_Transmitter);

  /* Test on BP_I2C EV6 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) /* EV6 */
  {
  }

  /* Send the specified register data pointer */
    I2C_SendData(BP_I2C, (uint8_t)RegValue);

  /* Test on BP_I2C EV8 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) /* EV8 */
  {
  }

  /* Send BP_I2C STOP Condition */
  I2C_GenerateSTOP(BP_I2C, ENABLE);
}

uint16_t BP_ReadReg(uint8_t RegName)
{
  __IO uint16_t RegValue = 0;

  /* Enable BP_I2C acknowledgement if it is already disabled by other function */
  I2C_AcknowledgeConfig(BP_I2C, ENABLE);

  /*--------------------------- Transmission Phase ----------------------------*/
  /* Send BP_I2C START condition */
  I2C_GenerateSTART(BP_I2C, ENABLE);

  /* Test on BP_I2C EV5 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_MODE_SELECT))  /* EV5 */
  {
  }

  /* Send STBP slave address for write */
  I2C_Send7bitAddress(BP_I2C, BP_ADDR, I2C_Direction_Transmitter);

  /* Test on BP_I2C EV6 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) /* EV6 */
  {
  }

  /* Send the specified register data pointer */
  I2C_SendData(BP_I2C, RegName);

  /* Test on BP_I2C EV8 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) /* EV8 */
  {
  }
  /*------------------------------ Reception Phase ----------------------------*/
  /* Send Re-STRAT condition */
  I2C_GenerateSTART(BP_I2C, ENABLE);

  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_MODE_SELECT))  /* EV5 */
  {
  }

  /* Send BP slave address for read */
  I2C_Send7bitAddress(BP_I2C, BP_ADDR, I2C_Direction_Receiver);

  /* Test on EV6 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))  /* EV6 */
  {
  }

  /* Test on EV7 and clear it */
  while (!I2C_CheckEvent(BP_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))  /* EV7 */
  {
  }

  /* Store BP_I2C received data */
  RegValue = (uint16_t)(I2C_ReceiveData(BP_I2C));       
  
  /* Disable BP_I2C acknowledgement */
  I2C_AcknowledgeConfig(BP_I2C, DISABLE);

  /* Send BP_I2C STOP Condition */
  I2C_GenerateSTOP(BP_I2C, ENABLE);

  /* Test on RXNE flag */
  while (I2C_GetFlagStatus(BP_I2C, I2C_FLAG_RXNE) == RESET)
  {}

  /* Store BP_I2C received data */
  RegValue|=(I2C_ReceiveData(BP_I2C) << 8);       
  
  /* Return register value */
  return (RegValue);
}

3 Replies

  • Hello Ekiuser,

    What device are you using to control the TCA9548A?  Is it one of TI's?  If so that I can move this post to their forum to help you debug you code.  We really only support the hardware.  It is clear to see the stop condition isn't being done properly by the master. 

    -Francis Houde

  • In reply to fhoude:

    Dear Francis,

    No, I´m afraid that it´s not a TI´s controller, I´m working with a ST microcontroller.

    But, the function to select one port with "writereg" function seem to be ok. If I only connect 1 i2c device in any of the TCA9548A port, I can read properly any i2c register of the connected device. If I only select 1 port I have no problem.
    The problem comes if I want to switch from one port to other port in order to read 2 different i2c devices connected to TCA ports. Coul it be HW problem?
  • In reply to ekiuser ekiuser:

    Hello Ekiuser,
    Do you have the schematics of your system? I want to look at it to make sure I know how everything is connected.

    You are switching in and out capacitive loading on the bus which might be the problem. You may want to put short delays after you set the stop condition before you try and communicate. This is just a guess at this point, but might be worth trying out.
    -Francis Houde