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-22 09:31 AM
I am able to read data using the Reload mode. But the issue we are facing that ,after receiving the first set of data the SCL line is pulled low. Because of that i am not able to read the next set of data. The issue only happens when i receive more than 255 length data . When the data length is less than 255 the SCL is pulled high after reading and no issues .
int8_t LL_I2C_MasterRx(uint8_t devAddr, uint8_t* rxbyte, uint16_t rxsize)
{
uint32_t request;
uint32_t mode;
// uint8_t cnt = 0;
uint16_t remaining = rxsize;
while (remaining > 0)
{
uint16_t currentTransferSize = (remaining > 255) ? 255 : remaining;
mode = (remaining > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND;
request = (remaining > 255) ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP;
LL_I2C_HandleTransfer(I2C1, devAddr, LL_I2C_ADDRSLAVE_7BIT, currentTransferSize, mode, LL_I2C_GENERATE_START_READ);
for (uint16_t i = 0; i < currentTransferSize; i++)
{
while (!LL_I2C_IsActiveFlag_RXNE(I2C1));
*rxbyte = LL_I2C_ReceiveData8(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
rxbyte++;
}
remaining -= currentTransferSize;
if (mode == LL_I2C_MODE_AUTOEND)
{
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
LL_I2C_ClearFlag_STOP(I2C1);
}
}
LL_I2C_GenerateStopCondition(I2C1);
return 0; // Return success (or handle error cases as needed
}
2024-08-22 09:58 PM
I am able to read data using Reload mode. But there is an issue happens , that is after reading the 284 data the SCL is pulled low . It never returns to High state. Because of that i am not able to read the next set of data. The SCL is pulled High in the case where the data is lesser than 255. Please find the code and scope image.
int8_t LL_I2C_MasterRx(uint8_t devAddr, uint8_t* rxbyte, uint16_t rxsize)
{
uint32_t request;
uint32_t mode;
// uint8_t cnt = 0;
uint16_t remaining = rxsize;
while (remaining > 0)
{
uint16_t currentTransferSize = (remaining > 255) ? 255 : remaining;
mode = (remaining > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND;
request = (remaining > 255) ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP;
LL_I2C_HandleTransfer(I2C1, devAddr, LL_I2C_ADDRSLAVE_7BIT, currentTransferSize, mode, LL_I2C_GENERATE_START_READ);
for (uint16_t i = 0; i < currentTransferSize; i++)
{
while (!LL_I2C_IsActiveFlag_RXNE(I2C1));
*rxbyte = LL_I2C_ReceiveData8(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
rxbyte++;
}
remaining -= currentTransferSize;
if(remaining == 1)
{
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
}
if (mode == LL_I2C_MODE_AUTOEND)
{
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
LL_I2C_ClearFlag_STOP(I2C1);
}
}
LL_I2C_GenerateStopCondition(I2C1);
return 0; // Return success (or handle error cases as needed
}
2024-08-23 03:29 AM
Hello @Sivakumarzcs128
Please find below the update of your code.
int8_t LL_I2C_MasterRx(uint8_t devAddr, uint8_t* rxbyte, uint16_t rxsize)
{
// uint8_t cnt = 0;
uint16_t remaining = rxsize;
uint16_t StartIDX=0;
while (remaining > 0)
{
uint16_t currentTransferSize = (remaining > 255) ? 255 : remaining;
if(remaining > 255) & (StartIDX == 0)
{
LL_I2C_HandleTransfer(I2C1, devAddr, LL_I2C_ADDRSLAVE_7BIT, currentTransferSize, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_READ);
StartIDX = 1;
}
else if ((remaining > 255) & (StartIDX != 0))
{
LL_I2C_HandleTransfer(I2C1, devAddr, LL_I2C_ADDRSLAVE_7BIT, currentTransferSize, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
LL_I2C_HandleTransfer(I2C1, devAddr, LL_I2C_ADDRSLAVE_7BIT, currentTransferSize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
for (uint16_t i = 0; i < currentTransferSize; i++)
{
while (!LL_I2C_IsActiveFlag_RXNE(I2C1));
*rxbyte = LL_I2C_ReceiveData8(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
rxbyte++;
}
remaining -= currentTransferSize;
if(remaining == 1)
{
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
}
if (mode == LL_I2C_MODE_AUTOEND)
{
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
LL_I2C_ClearFlag_STOP(I2C1);
}
}
LL_I2C_GenerateStopCondition(I2C1);
return 0; // Return success (or handle error cases as needed
}
To implement correctly your code with reload mode you need to implement the workaround in the Erratasheet (Section 2.12.5).