title: How to initialize I2C on STM32F0?
body: <p>Recently I've been trying to get the I2C bus working on the STM32F030F4P6 MCU, but with little luck.</p>
  
  <p>I'm using an STM32F0 module and have found plenty of resources for the STM32F1 module I2C initialization, but nothing specific about the STM32F0 initialization/transfer process.</p>
  
  <p>Here's my initialization code:</p>
  
  <pre><code>void i2c_init(uint8_t ownAddress)
  {
  GPIO_InitTypeDef  GPIO_InitStructure;
  I2C_InitTypeDef  I2C_InitStructure;
  
  // Enable GPIOA clocks
  
  RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  
  // Configure I2C1 clock and GPIO
  
  GPIO_StructInit(&amp;GPIO_InitStructure);
  
  
  /* I2C1 clock enable */
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
  
  /* I2C1 SDA and SCL configuration */
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_Init(GPIOA, &amp;GPIO_InitStructure);
  
  /* I2C1 Reset */
  
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
  
  
  /* Configure I2C1                */
  
  I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
  I2C_StructInit(&amp;I2C_InitStructure);
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  //I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  //I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
  
  
  I2C_Init(I2C1, &amp;I2C_InitStructure);
  I2C_Cmd(I2C1, ENABLE); 
  
  }
  </code></pre>
  
  <p>In order to test to see if my setup was correct I designed some I2C transmission code that would transfer data in a never ending loop. Here's the code for that:</p>
  
  <pre><code>while(1)
  {
  I2C_SlaveAddressConfig(I2C1, RegName);
  I2C_GenerateSTART(I2C1, ENABLE);
  I2C_NumberOfBytesConfig(I2C1, 8);
  I2C_SendData(I2C1,0b00000000);
  I2C_GenerateSTOP(I2C1, ENABLE);
  }
  </code></pre>
  
  <p>Where:</p>
  
  <p>RegName = 0x75</p>
  
  <p>SDA = GPIO_PIN_10 on GPIOA</p>
  
  <p>SCL = GPIO_PIN_9 on GPIOA</p>
  
  <p>I2C = I2C1</p>
  
  <p>ownAdrress = 0x68</p>
  
  <p>When I scope the I2C lines after I start this code I get a floating voltage around 160mV. When I step through the code every one of the I2C function calls happen and complete, so that's why I was thinking that it had something more so to do with my initialization of the pins themselves.</p>
  
  <p>My problem is very similar to this thread, but was never answered:</p>
  
  <p><a href="https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32F0%20I2C%20code%20doesn%27t%20work&amp;FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&amp;currentviews=1342" rel="nofollow noreferrer">https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32F0%20I2C%20code%20doesn%27t%20work&amp;FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&amp;currentviews=1342</a></p>
  
  <p><strong>Edit 1:</strong> Here's my latest code; still not working (<strong>Edit 2:</strong> Updated to what I currently have; moved things into more correct locations):</p>
  
  <pre><code>void i2c_init(uint8_t ownAddress)
  {
  
      /* TypeDefs for GPIOA and I2C1 */
  
      GPIO_InitTypeDef  GPIO_InitStructure;
      I2C_InitTypeDef  I2C_InitStructure;
  
      /* Enable GPIOA clocks and I2C1 clock enable */
  
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
  
      /* Configure I2C1 clock and GPIO */
  
      GPIO_StructInit(&amp;GPIO_InitStructure);
  
      /* I2C1 SDA and SCL configuration */
  
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //UP
      GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  
      /* GPIO AF Configuration -&gt; GPIO_AF_1: USART2, CEC, Tim3, USART1, USART2,EVENTOUT, I2C1, I2C2, TIM15 */
  
      GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
      GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
  
      GPIO_Init(GPIOA, &amp;GPIO_InitStructure);
  
      /* I2C1 Reset */
  
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
  
  
      //I2C_DeInit(I2C1);
  
      /* Configure I2C1 */
  
      I2C_StructInit(&amp;I2C_InitStructure);
  
      I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
      I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
      I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
      I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
      I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  
      I2C_Init(I2C1, &amp;I2C_InitStructure);
      I2C_Cmd(I2C1, ENABLE);
      //I2C_AcknowledgeConfig(I2C1, ENABLE);
  
  }
  </code></pre>
  
  <p>As you can see I added the two lines <code>GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);</code> and <code>GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);</code> where I found that GPIO_AF_1 had the alternate function of I2C1 from <a href="http://www.han-ese.nl/STM32/stm32f0stdlibrary/html/group___g_p_i_o.html#ga0a77617a322562ae84f8d72486032c5d" rel="nofollow noreferrer">the STM32F0 Standard Peripheral bibliotheek</a>. </p>
  
  <p>Any other ideas? I've been playing around with the clocks to see if that changed anything and have been adding snippets of other people's code just to see if that has any effect on the output of my device.</p>
  
  <p><strong>Edit 3:</strong> I have tried pulling both the SDA and SCL lines up to VCC with a 1kohm resistor as instructed by this guide: <a href="https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations">https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations</a></p>
  
  <p>->(3.3V-0.4)/3mA ~= 1kohm</p>
  
  <p><strong>Edit 4:</strong> After going through my code line by line I tried outputting various flag bit registers. Specifically these registers: <code>isr = I2C1-&gt;ISR;</code>, <code>cr1 = I2C1-&gt;CR1;</code>, and <code>cr2 = I2C1-&gt;CR2;</code> </p>
  
  <p>The flag I get after initiating the I2C transfer handling with <code>I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);</code> was <code>0x8001</code> which can be deciphered down to two errors:</p>
  
  <p><code>#define  I2C_ISR_BUSY                        ((uint32_t)0x00008000)        /*!&lt; Bus busy */</code></p>
  
  <p>and</p>
  
  <p><code>#define  I2C_ISR_TXE                         ((uint32_t)0x00000001)        /*!&lt; Transmit data register empty */</code></p>
  
  <p>I've found some work arounds at this link here (remove the space after https: to go to the link -> stack overflow won't let me post more than 1 link for some reason): https: //my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32L151RB%20I2C%20Busy%20flag%20always%20set&amp;FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&amp;currentviews=690 that I'm looking to implement and will report back as soon as I try them out.</p>