# STM32F3 I2C communication with Arduino

I am trying to implement the Inter-Integrated Circuit (I2C) of STM32F3 Discovery Board to communicate with 2 slaves (arduino) in my project. However, I cannot send any data to arduino.

Here is my coding:

    void I2CInit(I2C_TypeDef* I2Cx){

if (I2Cx == I2C1){

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB,&GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_4);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_4);

I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_AnalogFilter =  I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing = 0xA061191F;
I2C_Init(I2C1,&I2C_InitStructure);
I2C_Cmd(I2C1,ENABLE);
I2C_AcknowledgeConfig(I2C1,ENABLE);

I2C_Init(I2C1,&I2C_InitStructure);
I2C_Cmd(I2C1,ENABLE);
}

else {

GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure1.GPIO_OType = GPIO_OType_OD ;
GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA,&GPIO_InitStructure1);

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_4);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_4);

I2C_DeInit(I2C2);
I2C_InitStructure1.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure1.I2C_AnalogFilter =  I2C_AnalogFilter_Enable;
I2C_InitStructure1.I2C_DigitalFilter = 0x00;
I2C_InitStructure1.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure1.I2C_Timing =0x00902025;
I2C_Init(I2C2,&I2C_InitStructure1);
I2C_Cmd(I2C2,ENABLE);
I2C_AcknowledgeConfig(I2C2,ENABLE);

I2C_Init(I2C2,&I2C_InitStructure);
I2C_Cmd(I2C2,ENABLE);
}
}


I thinks I have done the I2C configuration correctly. Thus, I think the problem most probably come from the I2Cx_Write().

Test_Status I2Cx_Write(I2C_TypeDef* I2Cx, uint8_t *buff, uint32_t nbyte, uint8_t SlaveAddr){

/*--------Test on BUSY Flag-------------*/
__IO uint32_t timeout = 0xFFFF;

while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)!=RESET)
{
if (timeout-- == 0) return Error;
}

while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXIS)== RESET);
{
if((timeout--) == 0) return Error;
}

while(nbyte){
I2C_SendData(I2Cx, *buff++);
GPIOE->ODR |= 1L << 11;

while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE) == RESET);
nbyte-- ;
}

I2C_GenerateSTOP(I2Cx, ENABLE);

while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_STOPF) == RESET)
{
if((timeout--) == 0) return Error;
}

return Success;

}


Coding for Arduino:

#include <Wire.h>

void setup()
{
Wire.begin(8);
Serial.begin(115200);
}

void loop()
{
delay(100);
}

{
while (1 < Wire.available())
{
Serial.print(c);
}
Serial.println(x);
}


I will be very thankful if anyone can help me spot the problem.

Edit #1

I had tried using both I2C1 and I2C2 of STM32F3.

Edit #2

Actually it is okay if put the I2C_OwnAddress,it does not affect the STM32 as master in I2C communication.Just set any number will do. e.g. I set the I2C_OwnAddress = 0x2F; You only set it properly when use it as slave.

Edit #3

Some extra information:

Wire Connection:

I2C1:

PB6 - SCL

PB7 - SDA

I2C2:

PA9 - SCL

PA10 - SDA

*Do remember the common ground connection between the I2C devices.

• I dont see where you made the STM32 a master. Shouldnt that be one of the constants of I2C_Mode? You also seem to be assigning it an address, which is something you usually do for slaves. Why is this IF statement here when you must already know which I2C peripheral you're using? You also removed the disconnected the internal pull-ups;.you are using external ones? Have you tried debugging with print statements? Does it get stuck somewhere, or it just doesnt give the desired result? – TisteAndii Jul 12 '16 at 11:03
• Make sure that you have initialized I2C Peripheral correctly. Maybe having a look at this thread helps: my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/… – balboa Jul 12 '16 at 12:58
• According to the datasheet, STM32F3 acts as slave by default. It will become master when it generate START (S) by calling the I2C_TransferHandling(I2Cx,SlaveAddr,nbyte,I2C_AutoEnd_Mode,I2C_Generate_Start_Write); – Kalman Rotert Jul 12 '16 at 13:28
• I have problem to use I2C of STM32 too. I never could use it. I don't know why! – Roh Jul 12 '16 at 14:59

Yesterday just solve the I2C communication problem, just realize I have forget to configure the clock for I2C.

RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_I2CCLKConfig(RCC_I2C2CLK_SYSCLK);


Here is my clock configuration:

//activate clock for I2C1 and I2C2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
//config clock of I2C1 and I2C2
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_I2CCLKConfig(RCC_I2C2CLK_SYSCLK);


Now my STM32F3 can successfully using I2C to communication with arduino. And take note that the slave address in the I2Cx_Write(...) have to be left-shifted by 1 bit. For example, if the slave address is 21 (00010101), then the address you set in the I2Cx_Write(...) has to be 42 (00101010).