cancel
Showing results for 
Search instead for 
Did you mean: 

Low Layer API for I2C Communication in Stm32L031

Sivakumarzcs128
Associate II

Hi,

I have created a code snippet to communicate with I2C using LL API instead of HAL. The code is given below

 

uint8_t temp[2]={0xF9,0x00};

while(LL_I2C_IsActiveFlag_BUSY(I2C1)); // Wait until the I2C bus is not busy



LL_I2C_HandleTransfer(I2C1, 0x94, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);

LL_mDelay(10);

for (int i = 0; i < 2; i++) {

while (!LL_I2C_IsActiveFlag_TXE(I2C1)); // Wait until the data register is empty



if (LL_I2C_IsActiveFlag_NACK(I2C1)) { // Check for NACK (Not Acknowledged)



return 1;

}



LL_I2C_TransmitData8(I2C1, temp[i]); // Transmit data byte

LL_mDelay(10);

LL_I2C_ClearFlag_TXE(I2C1);



}



LL_I2C_GenerateStopCondition(I2C1);

LL_mDelay(10);

LL_I2C_ClearFlag_STOP(I2C1); // Clear the stop flag





// Reception (Rx)

LL_I2C_HandleTransfer(I2C1, 0x94, LL_I2C_ADDRSLAVE_7BIT, 16, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);



int i = 0;



// Wait for the stop condition or reception of 16 bytes

while (!LL_I2C_IsActiveFlag_STOP(I2C1)) {

if (LL_I2C_IsActiveFlag_RXNE(I2C1)) { // Check if data is received

Received[i++] = LL_I2C_ReceiveData8(I2C1); // Store received data

if (i >= 16) break; // Exit if 16 bytes have been received

}

}



// Ensure stop flag is cleared after reception is complete

if (LL_I2C_IsActiveFlag_STOP(I2C1)) {

LL_I2C_ClearFlag_STOP(I2C1);

}

 

 

 

i am able to transmit the data, but failed to read from the buffer. Anyone with prior experience in LL I2C can give me solution for this.

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Sivakumarzcs128 

To transfer data exceeding 255 bytes, you need to enable the reload mode.

LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);

 

This API should be called for each 255-byte transfer. The final call to this function should use the autoend mode.

In your case, you need to transfer 284 bytes, so you will call the API the first time with reload mode and the second time with autoend mode.

Here is the LL code for calling the function:

// First call with reload mode for the first 255 bytes
LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 255, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);

// ...

// Second call with autoend mode for the remaining 29 bytes
LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 29, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);

 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

View solution in original post

12 REPLIES 12
Saket_Om
ST Employee

Hello @Sivakumarzcs128 

 

Is the RXNE flag set? Or is the following if condition is true 

 

if (LL_I2C_IsActiveFlag_RXNE(I2C1))

 

Is the following instruction executed:

 

 

Received[i++] = LL_I2C_ReceiveData8(I2C1);

 

How the variable Received is declared? 

 

 

 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
Sivakumarzcs128
Associate II

The RXNE flag is set when the Handle transfer for read is completed and then reset when i check the stop flag condition. Also the variable received is declared as a buffer .

@Sivakumarzcs128 

Could you place a breakpoint on the following instruction and check if the data is being read from the SPI data register?

Received[i++] = LL_I2C_ReceiveData8(I2C1);

 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

i am always stuck here in this point 

while (!LL_I2C_IsActiveFlag_STOP(I2C1))

Also what are the things taken care during changing from HAL to LL in Stm32l031. 

@Sivakumarzcs128 

 

What is the device you are communicating with?  

You need to analyze why you are getting a stop condition after LL_I2C_HandleTransfer. it seems that the slave device is busy when sending the address.  

If I understand well in your application, you are sending a command {0xF9,0x00} and you are expecting to receive 16 bytes. 

Could you share with us the datasheet of the slave device please? 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
Sivakumarzcs128
Associate II

We have changed the code and now the I2C communication looks fine. Now we faces an issues of reading some data buffer ,where the buffer contains more than 255 data. 

LL_I2C_SetSlaveAddr(I2C1, (devAddr << 1) );

LL_I2C_SetTransferSize(I2C1, rxsize);

LL_I2C_SetTransferRequest(I2C1, LL_I2C_REQUEST_READ);

LL_I2C_GenerateStartCondition(I2C1);

 

The rxsize buffer is nearly 284, But the SetTransferSize parameter must be a value between Min_Data=0x00 and Max_Data=0xFF.

How can we read the remaing datas without losing any. given below is how we read the data

 

while(LL_I2C_IsActiveFlag_RXNE(I2C1))

{

*rxbyte = LL_I2C_ReceiveData8(I2C1);

LL_mDelay(5);

rxbyte++;

}

Hello @Sivakumarzcs128 

To transfer data exceeding 255 bytes, you need to enable the reload mode.

LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);

 

This API should be called for each 255-byte transfer. The final call to this function should use the autoend mode.

In your case, you need to transfer 284 bytes, so you will call the API the first time with reload mode and the second time with autoend mode.

Here is the LL code for calling the function:

// First call with reload mode for the first 255 bytes
LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 255, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);

// ...

// Second call with autoend mode for the remaining 29 bytes
LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 29, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);

 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

Hello @Sivakumarzcs128 

Has your issue been resolved by using the reload mode?

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
MOBEJ
ST Employee

hello @Sivakumarzcs128  , 

You can follow the examples provided in the STM32CubeL0 repository on GitHub. Specifically, you can refer to the  I2C LL examples for the NUCLEO-L073RZ board , it can help you to solve your issue : 

STM32CubeL0/Projects/NUCLEO-L073RZ/Examples_LL/I2C at master · STMicroelectronics/STM32CubeL0 · GitHub

 

BR

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.