2022-10-03 03:37 AM
I am using F411 to communicate with ADXL355 through I2C1.
I have a very strange issue:
LL_I2C_GenerateStartCondition(I2C1);
/* (1.3) Loop until Start Bit transmitted (SB flag raised) ********************/
/* Loop until SB flag is raised */
while(!LL_I2C_IsActiveFlag_SB(I2C1)) { }
/* (2.1) Send a 7-Bit SLAVE ADDRESS for a write request because my next step
is also write (putting register address on SDA line). */
LL_I2C_TransmitData8(I2C1, (dev_Addr << 1) | I2C_REQUEST_WRITE);
/* (2.2) Loop until ADDR flag is raised, i.e. address is fully sent */
while(!LL_I2C_IsActiveFlag_ADDR(I2C1)) { }
Sometimes the above code hangs at step 2.2 when I change other part of the firmware, which is totally unrelated to this one.
FYI I made my own PCB and run this code on it.
Can anybody give any advice or hint on why it happens?
2022-10-03 05:43 AM
Hello @HDaji.1 ,
Adding LL_I2C_ClearFlag_ADDR(I2C1); after line 12.
When your question is answered, please close this topic by choosing Select as Best. This will help other users find that answer faster.
Imen
2022-10-03 06:29 PM
Hello @Imen DAHMEN
Thank you for your advice. I have that LL_I2C_ClearFlag_ADDR after line 12. The issue is that it hangs at line 12, before reaching Clear Flag ADDR.
Here is the whole function:
void I2C_Read_1Byte(uint8_t dev_Addr, uint8_t reg_Addr, uint8_t *buffer) {
/* First Round, MCU transmits only so no need to Prepare ACK ******************/
//LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
/* (1.1) Initiate a Start condition to the Slave device ***********************/
/* Master Generate Start condition */
LL_I2C_GenerateStartCondition(I2C1);
/* (1.3) Loop until Start Bit transmitted (SB flag raised) ********************/
/* Loop until SB flag is raised */
while(!LL_I2C_IsActiveFlag_SB(I2C1)) { }
/* (2.1) Send a 7-Bit SLAVE ADDRESS for a write request because my next step
is also write (putting register address on SDA line). */
LL_I2C_TransmitData8(I2C1, (dev_Addr << 1) | I2C_REQUEST_WRITE);
/* (2.2) Loop until ADDR flag is raised, i.e. address is fully sent */
while(!LL_I2C_IsActiveFlag_ADDR(I2C1)) { }
/* (2.3) Clear ACK.*/
/* There is no Clear ACK function?? */
/* (2.4) Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(I2C1);
/* (3.1) Send data (for ADXL355, it is register address) on SDA line. */
LL_I2C_TransmitData8(I2C1, reg_Addr);
/* (3.2) Loop until Transmit data register empty flag is raised, i.e.
data fully sent LL_I2C_IsActiveFlag_TXE(I2C1) == 1 */
while(!LL_I2C_IsActiveFlag_TXE(I2C1)) { }
/* (3.3) Clear ACK*/
/* There is no Clear ACK function?? */
/* According to data sheet, we need to send ReStart */
/* (4.1) Since to receive ONE byte, we need to prepare NACK */
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
/* (4.2) Initiate a Start condition to the Slave device ***********************/
/* Master Generate Start condition */
LL_I2C_GenerateStartCondition(I2C1);
/* (4.3) Loop until Start Bit transmitted (SB flag raised) ********************/
/* Loop until SB flag is raised */
while(!LL_I2C_IsActiveFlag_SB(I2C1)) { }
/* (5.1) Send a 7-Bit SLAVE ADDRESS for a write request because my next step
is also write (putting register address on SDA line). */
LL_I2C_TransmitData8(I2C1, (dev_Addr << 1) | I2C_REQUEST_READ);
/* (5.2) Loop until ADDR flag is raised, i.e. address is fully sent */
while(!LL_I2C_IsActiveFlag_ADDR(I2C1)) { }
/* (5.3) Clear ACK.*/
/* There is no Clear ACK function?? */
/* (5.4) Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(I2C1);
/* (6.1) Loop until RXNE flag is raised */
while(!LL_I2C_IsActiveFlag_RXNE(I2C1)) { }
/* Read character in Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
*buffer = LL_I2C_ReceiveData8(I2C1);
/* (7) End of tranfer, Data consistency are checking into Slave process *****/
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
}
The above function reads one byte from a certain register in ADXL355, which is based on one of the I2C LL sample (polling) code in STM32Cube_FW_F4_V1.26.0.
I read somewhere that interrupt or DMA is recommended/supported instead of polling for I2C communication. I am going to re-write the above code with interrupt method and will post any issues or questions in this thread. I have been working with LL APIs for UART, SPI, and I2C for months, and found the I2C is very complicated to understand and implement.
2022-10-04 03:05 AM
Hi @Imen DAHMEN
I have coded I2C1_EV_IRQHandler, but cannot get correct result.
Do you have any advice on how to debug it?
Setting breakpoint in the middle of IRQ handler is not a good way, is it? It will break the I2C protocol.