cancel
Showing results for 
Search instead for 
Did you mean: 

How to add delays between I2C bytes to support TI mct8329a / mct8316

BFox.1
Associate III

The TI motor drivers mct8329a and mct8316 require 100us delay between i2c data bytes. This can't include the acknowledge bit, but requires holding down the clock between transfers for the 100us. it is due to a bug in the TI chips that can't stretch clocks. Not doing this properly (according to TI) causes the chip control to freeze requiring a reset to recover.

I'm using an STM32F429/439 MCU and my firmware is utilizing the STM32F4xx HAL, specifically the stm32f4xx_hal_i2c files. I'm using host mode on the ST for the driver chip slave. I have added blocking delays (using a 1us timer) to achieve the 100us delays to HAL_I2C_Master_Transmit, I2C_MasterRequestWrite(), HAL_I2C_Master_Receive() and I2C_MasterRequestRead() functions. I've had to tweak some of the status register setting, particularly the I2C_CR1_ACK flag.

I've been successful getting the behavior I need for most of the transactions. The transmits all work well, where I'm having difficulty is with the first two bytes of a five byte read. The read transaction just doe the 7 bit address write and the five bytes of read from the slave. (Four bytes to the payroll and a CRC.) I've posted one scope image that captures the full read transaction. Note the first two bytes of read (just after the write of the 7 bit address) is where there is no clock stretching by the master. The is read is the result of a immediately preceding write of a three byte address (7 bit I2C address followed by 16 bit register address.)

I've confirmed that with the single place where I don't have the 100us delay between bytes does indeed freeze the motor driver chip.

I've attached my modified driver file and the original. I've tried a considerable number of ways to get that break between the two bytes, but to no avail. This is going through the last part of HAL_I2C_Master_Receive since it is a five byte read.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

There's no way to do this with the STM32F4 I2C peripheral. There is no delay between bytes 1 and 2 when receiving. EV1 kicks off two bytes of reception.

TDK_0-1747015550539.png

 

I see two possibilities:

  • Bit bang I2C.
  • Act as a slave in the same bus and stretch the clock yourself.
If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

5 REPLIES 5
gregstm
Senior III

Not sure if this helps - but I recently implemented a one wire interface to the old Dallas Semi temperature sensors (DS18B20). It required precise microsecond timing. I don't use HAL, but used the following simple/efficient timing functions -


#define zero_usec_counter TIM6->CNT = 0
#define get_usec_counter ( TIM6->CNT )
#define delay_to_usec_count(x) while ( get_usec_counter < x )

eg.

one_wire_line_low;
zero_usec_counter;
delay_to_usec_count ( 960 );
one_wire_line_release;
zero_usec_counter;
delay_to_usec_count ( 70 );
out = one_wire_line_value;
delay_to_usec_count ( 480 );

TDK
Super User

There's no way to do this with the STM32F4 I2C peripheral. There is no delay between bytes 1 and 2 when receiving. EV1 kicks off two bytes of reception.

TDK_0-1747015550539.png

 

I see two possibilities:

  • Bit bang I2C.
  • Act as a slave in the same bus and stretch the clock yourself.
If you feel a post has answered your question, please click "Accept as Solution".
BFox.1
Associate III

TDK, thank you for the definitive response. I studied that diagram in the reference manual (that has slight different text than the version I was using), but never picked up that it indicates the two bytes must be sent back to back. Thanks.

We already have a work around in place to reset the motor driver when it freezes, but the frequency was too high for our application and causing issues. I did test with 200us gaps and the freeze of the TI chip is reasonably rare (one failure in 72 hours) for our application. We do recover the frozen chip with a reset within a few seconds.

Another option would be to slow down the I2C bus to see if that helps. There is technically no minimum frequency, and certainly you can slow it down by 10x without issues (other than lower bandwidth and slower response).

If you feel a post has answered your question, please click "Accept as Solution".
BFox.1
Associate III

TDK As it turns out, that was our first attempt to mitigate this. We dropped our SCK to 10kHz (100us period) and that showed no improvement. When I asked TI, the claim was it had to be 100us _after_ the 9th bit (ACK/NAK). When I first had the delays in place (except for between the 7-bit address and first receive byte _and_ bytes 1 and 2), I tested with a 200us gap and had much better failure rates.. Then, fixing the address / first read byte, I set the inter-byte delay at 100us (as my scope trace shows) and I got worse results, so I think we'll be able to manage with 200us between bytes and not have the delay between bytes one and two. Still testing.

Thanks again for your assistance.

Bill