This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI Will Not Return Slave Data

We are using a MMA8452Q accelerometer connected to an nRF51822 via TWI using the twi_hw_master. Reading the WHO AM I register is the first attempt to get the TWI running but no data is returned.

#define ACCELEROMETER_ADDRESS       0x1C           // if SA0 = 0
#define WHO_AM_I_REG                0x0D

data_array[0] = WHO_AM_I_REG;
twi_master_transfer((ACCEL_ADDRESS << 1) | !TWI_READ_BIT, data_array, 1, TWI_DONT_ISSUE_STOP);
twi_master_transfer((ACCEL_ADDRESS << 1) | TWI_READ_BIT, data_array, 1, TWI_ISSUE_STOP);

Here is the screenshot of the write command.

image description

  1. START
  2. Slave Address (0x1D shifted left 1 bit)
  3. WRITE bit
  4. ACK (why doesn't it get closer to 0v?)
  5. no STOP
  6. WHO AM I register (0x0D)
  7. ACK (why doesn't it get closer to 0v?)
  8. STOP (why is there a STOP?)

Here is the screenshot of the read command.

image description

  1. START
  2. Slave Address (0x1D shifted left 1 bit)
  3. ACK (why doesn't it get closer to 0v?)
  4. But then no data is returned

There is no data because NRF_TWI1->EVENTS_ERROR always equals 1 so twi_master_read() is exited before the data is transmitted. It is 0 until the command NRF_TWI1->TASKS_STARTRX = 1 is executed which sends out the first 9 clocks and Slave Address but also sets NRF_TWI1->EVENTS_ERROR = 1. During the write command the instruction TASKS_STARTTX = 1 does not set EVENTS_ERROR = 1 so the write command is not aborted.

Where do I go from here?

  • You start by working out why the waveform shows 1/2 voltage, either you have an electrical issue or your scope isn't set up correctly and you're not seeing what's actually happening. Do you have the grounds on the board and accelerometer connected to each other?

  • "You start by working out why the waveform shows 1/2 voltage, either you have an electrical issue or your scope isn't set up correctly and you're not seeing what's actually happening. Do you have the grounds on the board and accelerometer connected to each other?"

    I doubted this was a scope problem since the clocks and data appeared correct. Yes, the Master and Slave grounds are the same.

    The ACK amplitude is the first thing that I pursued when I saw the questionable ACK. But I was unable to determine the cause. It looked like line contention between the Master and Slave outputs but the Master was set as “disconnect high” (i.e. S0D1) so that was ruled out.

    The Slave is powered by a 2.0V LDO so if the LDO output was at its minimum (1.90V) it would be below the minimum operating voltage of the Slave (1.95V) and possibly (but highly unlikely) causing the problem. I tried powering the Slave directly from the battery (3.3V) which dropped the ACK voltage to about 1/3 of the battery voltage (apparently providing more drive) but still not close to 0V.

    There are 4.7K external pullups and when turning of the internal pullups (11K-16K) the ACK voltage did not change so the pullup resistance appeared acceptable.

    The Slave VOL is specified as 0.1 X VDD max therefore with VDD = 2.0V the VOL = 0.2V max at 0.5mA. With 4.7K pullups the current should be approximately 2.0V/4.7K = 0.43mA which is within range but clearly larger pullups resistors would be preferable.

    After reading your response I looked at the code more closely and found that the problem. When the pin configuration for SDA is reloaded in twi_master_clear_bus() (twi_hw_master.c) the stored value in data_pin_config = 0 which sets S0S1 (standard low, standard high). This was the “contention” I was looking for at the beginning and solved this problem. Now the WHO AM I register is read correctly.

    Thank you for the “push” to look more closely at the ACK problem.

    Blockquote

Related