2024-08-13 11:32 PM - last edited on 2024-09-13 02:33 AM by Amel NASRI
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.
Solved! Go to Solution.
2024-08-16 04:08 AM
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);
2024-08-14 02:37 AM - edited 2024-08-14 02:38 AM
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?
2024-08-14 02:58 AM
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 .
2024-08-14 03:34 AM
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);
2024-08-14 03:38 AM - edited 2024-08-14 03:44 AM
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.
2024-08-14 03:54 AM
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?
2024-08-16 02:56 AM
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++;
}
2024-08-16 04:08 AM
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);
2024-08-22 01:07 AM
Hello @Sivakumarzcs128
Has your issue been resolved by using the reload mode?
2024-08-22 02:44 AM
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 :
BR