cancel
Showing results for 
Search instead for 
Did you mean: 

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

MMust.5
Senior II

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

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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".

View solution in original post

14 REPLIES 14
RhSilicon
Lead

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

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
Guru

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".

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?

Here I found a code example where HAL_I2C_Master_Transmit is used to pass the address where the value should be written.
https://deviot.vn/tutorials/stm32f1.23165131/giao-tiep-i2c-voi-stm32.69174167
Pay attention to

 

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

 

In the DS3231_getTime() function.

0x00 here serves as a register address. I'm trying to understand how it works.

TDK
Guru

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".

I'm trying to understand how it works.

The HAL code is an implementation of the instructions described in the Reference Manual document, which each MCU has in the Documents tab of the website:

F407_DOC.png

F407_RM1.png

See UM1725: Description of STM32F4 HAL and low-layer drivers.

To open the HAL code, there is a F3 shortcut:

F407_Open_Dec.png

Open the code declaration, shows for example the code of the selected function:

F407_Func.png

Function code (The registers described in the Reference Manual are handled in the function):

F407_REG.png

Reference Manual (The registers described in the Reference Manual are handled in the function):

F407_RM.png

There are 3 main documents for each MCU model, 1- Reference Manual, 2- Datasheet, 3- Programming Manual. With these 3 documents it's easier to understand what the HAL code is implementing.

- Reference Manual targets application developers. It provides complete information on how to use the MCU

- Datasheet provides the description of the MCU

- Programming Manual provides information for application and system-level software developers. It gives a full description of the STM32 Cortex ® -M4 processor programming model, instruction set and core peripherals

Some more complex topics, such as DMA, may have dedicated documents.

The YouTube channel also has videos on the application of MCUs and tools (STM32CubeIDE and others)

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?

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