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.

12 REPLIES 12

 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

}

 

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

}

 

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

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

Thanks
Omar