Skip to main content
MMust.5
Senior
August 16, 2023
Solved

I don't understand how to use the HAL_I2C_Master_Transmit function. RTC DS3231

  • August 16, 2023
  • 14 replies
  • 30802 views

I am using I2C to transfer data from STM32F4 to DS3231 Real Time Clock registers.

HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

*hi2c - I2C structure
DevAddress - Device address

*pData - I don't understand this parameter.
It is written on the Internet that this is a pointer for data, but this pointer is used to transfer the register address in the Slave device.

Size - data size in Bytes.

What parameter should the data be passed?

I can use the HAL_I2C_Mem_Write function. This function has a parameter for data transfer.
This parameter is also called *pData
HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

 

int main()
{
uint8_t RegisterAddress=0x0;
HAL_I2C_Master_Transmit(&hi2c1, 0xD0, &RegisterAddress, 1, 1000 );
}

 

I think that something is wrong with the &RegisterAddress parameter, but I don’t understand how it will be right.

As a result, I need to write data to the I2C Slave Device at the address I chose.

png.png

This topic has been closed for replies.
Best answer by TDK

Yes, you can also use HAL_I2C_Master_Transmit. It expects the address first, then the data, so you need a buffer with that in it, and then send all bytes.

TDK_0-1692237075304.png

So to write the value 42 to address 0:

uint8_t data[2] = {0, 42};
HAL_I2C_Master_Transmit(&hi2c1, 0xD0, &data, 2, 1000);

 

 > HAL_I2C_Master_Transmit(&hi2c1, DS3231_ADDRESS, 0x00, 1, 1000);

This is buggy code, don't do this. It expects a pointer, not data.

14 replies

RhSilicon
Lead
August 16, 2023

See this DS3231 driver, maybe it's easier to understand: https://github.com/rtek1000/Datalogger_2039/blob/main/Software/Datalogger_2039%20-%20STM32/Datalogger2039_DS3231_Test/Core/Src/DS3231.c

 

I don't know if it can help in your case, but I found these videos about advanced debugging:

STM32CubeIDE Advanced Debug Features

MMust.5
MMust.5Author
Senior
August 16, 2023

In this code, data is passed through the *pData parameter.
And how does the HAL_I2C_Master_Transmit function know at what address this data should be written?
DevAddress(second parameter) - is the address of the I2C Slave Device, not the address where data should be written to.

The address for the register that contains seconds in the DS3231 is 0x0.

png.png

TDK
August 16, 2023

You want HAL_I2C_Mem_Write.

uint8_t data = 0;
HAL_I2C_Mem_Write(&hi2c1, 0xD0, 0, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
MMust.5
MMust.5Author
Senior
August 16, 2023

Absolutely right.
I can use the HAL_I2C_Mem_Write function.
I am trying to use HAL_I2C_Master_Transmit in the same way as HAL_I2C_Mem_Write.
Aren't they similar functions?

Can't the HAL_I2C_Master_Transmit function do the same as the HAL_I2C_Mem_Write function?

TDK
TDKBest answer
August 17, 2023

Yes, you can also use HAL_I2C_Master_Transmit. It expects the address first, then the data, so you need a buffer with that in it, and then send all bytes.

TDK_0-1692237075304.png

So to write the value 42 to address 0:

uint8_t data[2] = {0, 42};
HAL_I2C_Master_Transmit(&hi2c1, 0xD0, &data, 2, 1000);

 

 > HAL_I2C_Master_Transmit(&hi2c1, DS3231_ADDRESS, 0x00, 1, 1000);

This is buggy code, don't do this. It expects a pointer, not data.

"If you feel a post has answered your question, please click ""Accept as Solution""."
MMust.5
MMust.5Author
Senior
August 17, 2023

Ok, very interesting, I have not seen this information anywhere.
I managed to transfer data to the address as you wrote.
I read data from the register with the HAL_I2C_Mem_Read function.
Can the HAL_I2C_Master_Receive function read data from the register?

I tried to first transfer only the address of the register, and then read using the HAL_I2C_Master_Receive function.
But that doesn't work.

 

uint8_t result[10]={0};
uint8_t data[2]={0,7};
HAL_I2C_Master_Transmit(&hi2c1, 0xD0,data, 2, 1000 );

//----------------------------------------------------
HAL_I2C_Master_Transmit(&hi2c1, 0xD0, 0x0, 1, 1000 ); //Attempt to read register 0x00
HAL_I2C_Master_Receive(&hi2c1, 0xD1, result, 1, 1000 ); //Attempt to read register 0x00
//----------------------------------------------------

 

Maybe it works the same way?

RhSilicon
Lead
August 17, 2023

@MMust.5 wrote:

I did not find any extended information on the HAL_I2C_Master_Transmit function.
There are a lot of incorrect codes on the Internet with this function, there are even videos on YouTube with the incorrect use of HAL_I2C_Master_Transmit.
Only TDK explained to me how to use this function correctly.

UM1725

png.png


 

It might be interesting to study the C language, there are tutorials on the internet.

https://www.w3schools.com/c/c_pointers.php

MMust.5
MMust.5Author
Senior
August 17, 2023

Before asking a question, I tried many times to figure it out myself.
Why do I need links to Wikipedia in the topic?
You send me to learn C, as if I were asking about the operation of the printf function.
Thanks, but I don't need any more instructions from you.

I describe all my questions in great detail, trying to help not only myself, but also those who will be looking for an answer to this question.
Your "very necessary instructions" filled my entire topic.
To be honest, this is the first time I've seen this on this forum.

Pavel A.
August 17, 2023

Well, now it is clear that you don't know about I2C "repeated start" transactions (write then read in one transaction). You may want to google/bing/chatgpt it for better understanding.  HAL_I2C_Mem_Read does the "repeated start" thing.

MMust.5
MMust.5Author
Senior
August 17, 2023

I don't use HAL_I2C_Mem_Read
Yes, I know that HAL_I2C_Mem_Read reads the value at the selected address in one function.

What makes this function unique is that it first performs an I2C transmit operation to tell the slave device what memory address to source the data from. This is followed by a repeated start condition to begin the receive operation. The complete I2C sequence is shown below. Note that HAL_I2C_Mem_Read() is the only function capable of generating a repeated start condition in blocking mode. If a repeated start is required, it is not sufficient to call HAL_I2C_Master_Transmit() immediately followed by a call to HAL_I2C_Master_Receive().

My task was to do exactly that with the HAL_I2C_Master_Receive function.
The issue has been resolved, thanks everyone.