I2C_RTOS_Transfer does not send Stop if dataSize is 0

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

I2C_RTOS_Transfer does not send Stop if dataSize is 0

ソリューションへジャンプ
1,251件の閲覧回数
beng_
Contributor III

I've found that I2C_RTOS_Transfer does not send a Stop if dataSize is 0.

Am I doing something wrong or is there a bug is the API?

I'm using a Sensirion SHT 21 (datasheet).

One of the command available is to send a soft reset (easily explained via screen shot from the data sheet).

pastedImage_3.png

My I2C is configured as follows:

status_t status;
i2c_master_config_t i2c_master_config;
uint32_t i2c_source_clock_hz;

I2C_MasterGetDefaultConfig(&i2c_master_config);
i2c_master_config.baudRate_Bps = 10000;
i2c_master_config.enableMaster = false;

i2c_source_clock_hz = CLOCK_GetFreq(kCLOCK_CoreSysClk);

CLOCK_EnableClock(kCLOCK_I2c0);
status = I2C_RTOS_Init(&i2c_rtos_handle, I2C0, &i2c_master_config,
                       i2c_source_clock_hz);

/* Disable I2C module and gate its clock */

I'm sending a soft reset in the following manner:

static void soft_reset_sht(void)
{
  i2c_master_transfer_t i2c_soft_reset;

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = SHT_SOFT_RESET;
  i2c_soft_reset.subaddressSize = 1;
  i2c_soft_reset.data = NULL;
  i2c_soft_reset.dataSize = 0;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;


  I2C_Enable(I2C0, true);

  I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );

  // Disable I2C hardware
  I2C_Enable(I2C0, false);

  return;
}

This doesn't' send a stop command and leaves SCL low:

pastedImage_12.png

If I add in some dummy data and send a send it (i.e. i2c_soft_reset.dataSize is not set to zero) the an I2C stop is correctly sent.

static void soft_reset_sht(void)
{
  i2c_master_transfer_t i2c_soft_reset;
  uint8_t local_u8_buffer[1];

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = SHT_SOFT_RESET;
  i2c_soft_reset.subaddressSize = 1;
  i2c_soft_reset.data = local_u8_buffer;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;


  I2C_Enable(I2C0, true);

  I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );


  I2C_Enable(I2C0, false);

  return;
}

This gives

pastedImage_9.png

ラベル(1)
タグ(2)
0 件の賞賛
返信
1 解決策
1,020件の閲覧回数
visakhanc
Contributor III

Hi Ben,

For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = 0;
  i2c_soft_reset.subaddressSize = 0;
  i2c_soft_reset.data = SHT_SOFT_RESET;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;

 

Regards,

Visakhan

元の投稿で解決策を見る

0 件の賞賛
返信
1 返信
1,021件の閲覧回数
visakhanc
Contributor III

Hi Ben,

For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = 0;
  i2c_soft_reset.subaddressSize = 0;
  i2c_soft_reset.data = SHT_SOFT_RESET;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;

 

Regards,

Visakhan

0 件の賞賛
返信