cancel
Showing results for 
Search instead for 
Did you mean: 

HAL I2C Transmit then Receive without a stop between

SnoZek
Associate II

Hello,

I’m using an STM32WBA65 and trying to communicate with a peripheral (PTX30W) over I2C1.

The peripheral requires the following I²C sequence:

 
STARTWRITE → REPEATED STARTREAD → STOP

However, using HAL_I2C_Master_Transmit() followed by HAL_I2C_Master_Receive() does not work, because both HAL functions generate a STOP condition, and the PTX30W does not accept a STOP between the write and read phases.

On STM32WBA, I don’t see a HAL equivalent of HAL_I2C_Master_TransmitReceive() that would allow a repeated START without a STOP in between.

My questions are:

  • Is there a way to achieve a WRITE + REPEATED START + READ sequence using the HAL on STM32WBA?

  • Or is the correct approach to switch to the LL (Low Layer) I2C driver to get finer control over START/STOP conditions?

Any guidance or best practices for this use case would be appreciated.

Thanks in advance.


here is the i2c protocol :

SnoZek_0-1766073089303.png

7 REPLIES 7
TDK
Super User

Use HAL_I2C_Mem_Read to write 1-2 bytes, then read a bunch, using a repeated start.

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

@TDK wrote:

Use HAL_I2C_Mem_Read to write 1-2 bytes, then read a bunch, using a repeated start.


@Emil Damkjaer PETERSEN @Loic CHOSSAT this is particularly poorly described in the HAL documentation:

AndrewNeil_0-1766076967189.png

https://www.st.com/resource/en/user_manual/um3140-description-of-stm32wba-hal-and-lowlayer-drivers-stmicroelectronics.pdf#page=327

 

I really don't think it's at all clear from this description that "MEM" is the one to use in this application?

 

Please can we have a clear description like @TDK's in the HAL manuals - this kind of question comes up frequently on the forum!

I suspect that most applications where HAL_I2C_Mem_Read is the correct choice are not actually "memory" devices - as is the case here.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
TDK
Super User

I think the HAL_I2C_Mem_Read naming is appropriate. Most uses of this are for actual memory addresses or register analogs. For example, accelerometers and other sensors, EEPROMs, LCD character displays. Just my opinion.

If you feel a post has answered your question, please click "Accept as Solution".
Danish1
Lead III

I suspect that most I2C peripherals will actually work with a write followed by a read where the data-sheet shows repeated-start.

A major difference between the two is that after a stop-condition (on completion of the write) the I2C bus is released. In a multi-master system, a different I2C master may take control of the I2C bus and do whatever it wants.

If bus-master A sets up the peripheral address that it wants to read-from and then releases the bus before it actually does the read, bus-master B might change that address and so the wrong value will be read by A.

Many I2C systems just have the one bus master, so the problem cannot arise. But because I2C can be multi-master, peripheral data-sheets are written to suggest doing things in a way that is compatible with multi-master.

On reflection, multi-master issues can also arise where there is just the one hardware I2C master (your stm32) but it is running multiple threads and more than one oc those threads communicates over the I2C

SnoZek
Associate II

Hello,

Thanks for your answer, but before reading i have to send 4 bytes and mem_read can only accept size of 8bits or 16 bits : 

in HAL_I2C_Mem_Read() :

assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));

So, it's not usable here.

And i already tried to make it work with the stop between writing and reading but it's not working.

I guess i will have to use lower level library.

Curious question, why is there no i2c transmitreceive function where you can write and read with a repeated start?


Thanks for your answers,


@SnoZek wrote:

why is there no i2c transmitreceive function where you can write and read with a repeated start?


There is - that's what HAL_I2C_MEM_Read does.

But, as you say, the read part is limited.

And, as I said, the description does not give any clue as to what it actually does.

 


@SnoZek wrote:

 guess i will have to use lower level library.


You could start by looking at the source of HAL_I2C_MEM_Read - see if that can be easily adapted ...

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
TDK
Super User

There are HAL_I2C_Master_Seq_Transmit_(IT/DMA) and HAL_I2C_Master_Seq_Receive_(IT/DMA) functions that could be used here. No blocking ones.

 

Writing 4 bytes and then reading a bunch is not a typical use case.

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