cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 I2C2 SDA improper data

GenuineDeveloper
Associate III

I have already used I2C1 successfully on STM32F051. However, when I am trying to use the I2C2 on STM32F051R8T6, the problem is that the voltage level of the data received on SDA line seems to be chopped. Am I doing anything wrong with the initialization section for I2C2 in particular? How about the clock source, I have not specifically mentioned any clock source for I2C using RCC_I2CCLKConfig() function, since I have read that I2C uses PCLK as its clock source unlike I2C1.

Kindly help me in resolving this issue.

Note: I have used 4.7K as pullup as device(BQ32000) datasheet suggest.

/********** GPIO INIT FOR I2C2 ******************/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
 
GPIO.GPIO_Pin  = GPIO_Pin_6| GPIO_Pin_7;		//I2C2 PF6|PF7
GPIO.GPIO_Mode = GPIO_Mode_AF;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_UP;
GPIO.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_PinAFConfig(GPIOF, GPIO_PinSource6,GPIO_AF_1);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource7,GPIO_AF_1);
GPIO_Init(GPIOF, &GPIO);
}
 
/*******      FUNCTION TO INITIALIZE I2C2    ************/
void I2C_Setup(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
 
I2C_InitTypeDef I2C2_Init;
I2C2_Init.I2C_Mode = I2C_Mode_I2C;
I2C2_Init.I2C_OwnAddress1 = 0;
I2C2_Init.I2C_Ack = I2C_Ack_Enable;
I2C2_Init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C2_Init.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C2_Init.I2C_DigitalFilter = 0;
I2C2_Init.I2C_Timing = 0x10802E3D;  // At 24000000 MHz, 500ns Rise, 150ns Fall as per device datasheet
I2C_Init(I2C2, &I2C2_Init);
I2C_Cmd(I2C2, ENABLE);
}
 
/******* FUNCTION TO READ BYTE ************/
uint8_t I2C_Read_Byte(void)
{
uint8_t cTempSec;
 
//Check if I2C peripheral isn't busy
while(I2C_GetFlagStatus(I2C2,I2C_ISR_BUSY));	
 
//Start I2C Read transfer for 1 byte, do not end transfer
I2C_TransferHandling(GPIOF,(I2C_SLAVE_WRITE_ADDRS),1,I2C_SoftEnd_Mode,I2C_Generate_Start_Write);
// I2C_SLAVE_WRITE_ADDRS = 11010000
 
while(I2C_GetFlagStatus(I2C2,I2C_ISR_TXIS));
I2C_SendData(I2C2,RTC_SEC_ADDRS);
while(I2C_GetFlagStatus(RTC_I2C,I2C_ISR_TC));
 
// Repeated start I2C read transfer for 1 byte
I2C_TransferHandling(I2C2,(I2C_SLAVE_READ_ADDRS),1,I2C_AutoEnd_Mode,I2C_Generate_Start_Read);	
// I2C_SLAVE_WRITE_ADDRS = 11010001
 
while(I2C_GetFlagStatus(I2C2,I2C_ISR_RXNE));
cTempSec = I2C_ReceiveData(I2C2);
// Wait and clear stop flag
while(!(I2C_GetFlagStatus(I2C2,I2C_ISR_STOPF)));
I2C_ClearFlag(I2C2,I2C_ICR_STOPCF);
return cTempSec;
}

0690X0000060OtsQAE.jpg

From the above image you can see that the pulses seems to be chopped.

The first set on SDA defines the slave read address, 11010001, the last bit 1 is not proper. What could be the reason?

3 REPLIES 3

GPIO.GPIO_OType = GPIO_OType_PP;

I2C expects Open-Drain, not Push-Pull

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
GenuineDeveloper
Associate III

Yes, agreed. I tried both to check, OD as well as PP, but there was no change in the output(the code had the later PP config that I had tried).

David Littell
Senior III

Pins used for I2C don't need the internal pullups/pulldowns enabled. Those little spikes you're seeing are when the SDA is released following the ACK clock interval. They don't normally indicate a problem.

What's shown on the scope trace is an I2C write (SDA at the rising edge of the 8th SCL is a 0). This is from line 40 in your code.

I'd suggest you fix the comments to match the code.