Getting Started and Peripheral Coding STM32 MCU's STM32F1 Tech

Overview

In this blog we will be discussing another special functionality of GPIO pins I2C or Inter-Integrated Circuit or I2c functionality . I2C is a two wire interface or TWI which was developed by the Philips corporation for use in consumer products . It is a bidirectional bus that can be easily implemented in an IC process.I2C combines best features of SPI as well as UART it lets the user control multiple slaves via multiple masters which is useful when logging data to sd cards or displaying on LCD. Just like SPI the output data bits are synchronized to sampling of the clock shared by both the parties involved in the communication . The master always generates the clock.The protocol finds applications in hardware sensors or displays , reading memory ICs , communicating with microcontrollers , ADC or DACs.

I2C Theory

I2C consists of 2 lines SCL and SDA

 1.SCL (Serial Clock ) – For synchronizing data transfer between master and slave 

 2, SDA (Serial Data ) – The data transmission or receiving line

Multiple Master and Slave lines are connected to the SDA and SCL lines and both these lines are pulled up using resistors to Vdd (5v)

Operation Modes In I2C 

  • Master Transmitter
  • Master Receiver
  • Slave Transmitter 
  • Slave Receiver 

I2C Clock Speed

The speed of the I2C bus should be in reference to the one provided in the datasheet

The modes of I2C clock speed are as follows:-

  • Standard-mode : 100 KHZ max
  • Fast-mode: 400 KHz max
  • Fast-mode Plus:1MHz
  • High-speed mode: 3.4 MHz

I2C duty cycle specifies the ratio between Tlow and Thigh of the I2C SCL line

The values being:

I2C_DUTYCYCLE_2=2:1

I2C_DUTYCYCLE_16_9= 16:9

 The desired clock speed can be achieved using the appropriate duty cycle to prescale

How data is transmitted in I2C Protocol

 

I2C Features in STM32F103

I2C Instances in STM32F103

The I2C instances vary from microcontroller to microcontroller i.e the stm32f103c676A has one I2c instance with stm32 f411 RE having I2C1 and I2C2 . The pins for I2C1 are 

  • PB7 – This is used as SDA 
  • PB6 – This is used as SCL

The pins for I2C2 are:-

  • PB3 – This is used as SDA
  • PB10 – This is used as SCL

I2C configuration Parameters in STM32F103

This parameter defines the clock speed which as mentioned previously can be 100000 in standard mode and 400000 fast mode.

This parameter helps in configuring the HIGH and LOW ratio of the clock and has value 2:1 and 16:9

This parameter takes in the address of the first device which can be 7 bit or 10 bit long

This parameter suggests the type of the address size being chosen which can be 7 bit or 10 bit

This parameter is used to disable or enable the dual addressing mode of I2C

This parameter is used to disable or enable the general call addressing mode.

This parameters checks the nostrech mode

Applications of I2C

SSD1306 OLED Screen with STM32F103
GEsture sensor with STM32F103
Time of Flight Sensor with STM32F103
INA219 DC Current Sensor with STM32F103

How to configure the I2C peripheral in STM32F103

We would be using STM32 HAL and STM32CubeIDE for using the I2C peripheral in STM32F103 in this blog tutorial series.

CONFIGURATION IN STM32CUBEIDE

FIG 1- Selecting the SCL and SDA pin

FIG 2 – Configuring the i2c parameters

I2C data handling API types

SDK files

  1. Stm32f1xx_hal.c
  2. Stm32f1xx_hal_i2c.c
  3. Stm32f1xx_hal_i2c.h

The hal.c contains all the macros , function declarations , alternate function mapping of GPIO peripheral and Clock Configurations .The i2c.c file contains initialization and declaration of various low level registers , macros , static void functions , callback functions  , configuration of various parameters of both master as well as slave . The i2c.h file contains all the enums , structure parameters such as clock speed , ownaddress declarations etc.It also contains the declaration of macros of the values that will be filled by the structure parameters such as duty cycle value .

HAL APIs Involved

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Init (I2C_HandleTypeDef * hi2c)

FUNCTION DESCRIPTION

Initializes the I2C according to the specified parameters in the I2C_InitTypeDef and initialize the associated handle. 

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C

 RETURN VALUES 

  •  HAL: status
				
					HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
{
  uint32_t freqrange;
  uint32_t pclk1;

  /* Check the I2C handle allocation */
  if (hi2c == NULL)
  {
    return HAL_ERROR;
  }


				
			

FUNCTION NAME

void HAL_I2C_MspInit (I2C_HandleTypeDef * hi2c)

FUNCTION DESCRIPTION

Initialize the I2C MSP.

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C

 RETURN VALUES 

  •  HAL: status

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Master_Transmit (I2C_HandleTypeDef * hi2c, uint16_t DevAddress, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Transmits in master mode an amount of data in blocking mode according to the values in the parameters 

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  DevAddress: Target device address: The device 7 bits address value in datasheet must be shifted to the left before calling the interface 
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration

 RETURN VALUES 

  •  HAL: status
				
					 while (1)
  {
	  ret = HAL_I2C_Master_Transmit(&hi2c1,  (4 << 1),(uint8_t *)dataBuffer, 11, 100);
;
				
			

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Master_Receive (I2C_HandleTypeDef * hi2c, uint16_t DevAddress, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Receives in master mode an amount of data in blocking mode according to the values in the parameters 

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  DevAddress: Target device address: The device 7 bits address value in datasheet must be shifted to the left before calling the interface 
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration

 RETURN VALUES 

  •  HAL: status
				
					while (1)
  {
	  ret = HAL_I2C_Master_Receive(&hi2c1,  (6 << 1),(uint8_t *)dataBuffer2, 11, 100);

	  if ( ret != HAL_OK ) {
	  	HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_7, 1);

				
			

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Slave_Transmit (I2C_HandleTypeDef * hi2c, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Transmits in slave  mode an amount of data in blocking mode according to the values in the parameters 

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration

 RETURN VALUES 

  •  HAL: status
				
					 while (1)
  {
	  HAL_I2C_Slave_Transmit(&hi2c1,(uint8_t *)dataBuffer3, 16, 80);

				
			

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Slave_Receive (I2C_HandleTypeDef * hi2c, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Receive in slave  mode an amount of data in blocking mode according to the values in the parameters 

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration

 RETURN VALUES 

  •  HAL: status
				
					 while (1)
  {
	  HAL_I2C_Slave_Receive(&hi2c1,(uint8_t *)dataBufferrr, 10, 100);


				
			

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Mem_Write (I2C_HandleTypeDef * hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Write an amount of data in blocking mode to a specific memory address.

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration
  • MemAddress:The address of the memory that has to be written
  • MemAddSize: The size of memory address
  • DevAddress:The device 7 bits address value in datasheet must be shifted to the left before calling the interface

 RETURN VALUES 

  •  HAL: status

FUNCTION NAME

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef * hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t * pData, uint16_t Size, uint32_t Timeout)

FUNCTION DESCRIPTION

Read an amount of data in blocking mode to a specific memory address.

PARAMETERS

  •  hi2c: Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
  •  pData: Pointer to data buffer
  •  Size: Amount of data to be sent 
  •  Timeout: Timeout duration
  • MemAddress:The address of the memory that has to be read
  • MemAddSize: The size of memory address
  • DevAddress:The device 7 bits address value in datasheet must be shifted to the left before calling the interface

 RETURN VALUES 

  •  HAL: status

FUNCTION NAME

static void MX_I2C1_Init(void)

FUNCTION DESCRIPTION

This function is used to intialize the I2C1 along with the parameters

PARAMETERS

NONE

RETURN VALUES

NONE

				
					static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

				
			

CODE

Sending code to arduino using I2C via STM32

				
					#include "main.h"

/* Private includes ----------------------------------------------------------*/
int ret;
char dataBuffer[] = "Hello world!";

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  ret = HAL_I2C_Master_Transmit(&hi2c1,  (4 << 1),(uint8_t *)dataBuffer, 11, 100);
	     
	  if ( ret != HAL_OK ) {
	  	HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_7, 1);
	  								 }
	  		 
	  		
	  if ( ret == HAL_OK ) {
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); 

	  HAL_Delay(200);
	  						 }
	  HAL_Delay(1000);  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


				
			
Kunal Gupta
Author: Kunal Gupta

Author

Kunal Gupta

Leave a comment

Stay Updated With Us

Error: Contact form not found.

      Blog