Skip to main content
Visitor II
February 10, 2020
Question

I2C Low level.

  • February 10, 2020
  • 11 replies
  • 5657 views

I want to implement a I2C low level driver on STM32L475 as I work with others chips.

int I2C_Wait(I2C_TypeDef * I2Cx)
{
 unsigned int timeout = 0;
 
 while(LL_I2C_IsActiveFlag_NACK(I2Cx) == 0)
 {
 if(++timeout > I2C_TIMEOUT)
 {
 LL_I2C_ClearFlag_NACK(I2Cx);
 return -1;
 }
 } 
 
 LL_I2C_ClearFlag_NACK(I2Cx);
 
 return 0;
}
 
void I2C_Read(I2C_TypeDef * I2Cx, uint8_t slave_addr, uint8_t reg_addr, uint8_t *data)
{
 
 /*----------first step - set register address to read from-----------*/
 
 uint8_t address = slave_addr & 0xFE; 
 
 LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE);
 
 // send start signal 
 LL_I2C_GenerateStartCondition(I2Cx);
 
 //send slave
 LL_I2C_TransmitData8(I2Cx, address);
 I2C_Wait(I2Cx);
 
 //send register address
 LL_I2C_TransmitData8(I2Cx, reg_addr);
 I2C_Wait(I2Cx);
 
 /*-----------second step - read from the written register address-----*/
 
 //slave address for read
 address = slave_addr | 0x01;
 
 //Repeated Start 
 LL_I2C_GenerateStartCondition(I2Cx);
 
 LL_I2C_TransmitData8(I2Cx, address);
 I2C_Wait(I2Cx);
 
 LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ);
 
 LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_ACK);
 
 *data = LL_I2C_ReceiveData8(I2Cx);
 
 for (delay = 0; delay < 1000; delay++) ; 
}
 
void I2C_Write(I2C_TypeDef * I2Cx, uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
 //for write operation R/Wn bit should be low
 uint8_t address = slave_addr & 0xFE; 
 
 LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE);
 
 // send start signal 
 LL_I2C_GenerateStartCondition(I2Cx);
 
 // send ID with W/R bit 
 LL_I2C_TransmitData8(I2Cx, address);
 I2C_Wait(I2Cx);
 
 // Write Register Address 
 LL_I2C_TransmitData8(I2Cx, reg_addr);
 I2C_Wait(I2Cx);
 
 LL_I2C_TransmitData8(I2Cx, data);
 I2C_Wait(I2Cx);
 
 LL_I2C_GenerateStopCondition(I2Cx);
 
 for (delay = 0; delay < 1000; delay++) ; 
}
 

But it doesn't work. What could be a problem?

    This topic has been closed for replies.

    11 replies

    Graduate
    February 11, 2020

    There's a complication with taking snapshots using the debugger, in that reading certain registers will change the state of the I2C peripheral.

    I found the flowcharts and transfer bus diagrams in the reference manual to be the right thing to follow. So that's Section 39.4.8 I2C Master Mode with figures 407, 409, 411, 412 of RM0351 Rev 6.