STM32CubeMX study notes (9)-I2C interface use

1. Introduction to I2C

I2C (Inter-Integrated Circuit, Inter-Integrated Circuit) bus is a serial bus developed by Philips Philip Company. It is two serial buses, which consist of a data line (SDA) and a clock line (SDL). Multiple I2C devices can be connected to the I2C bus, and each device has a unique address identification. There can only be one master device at a time, and the others are slave devices. Usually the MCU is controlled as the master device and the peripherals are used as the slave device.

STM32's I2C peripherals can be used as communication masters and slaves, support 100Kbit/s and 400Kbit/s rates, support 7-bit and 10-bit device addresses, support DMA data transmission, and have a data check function. Its I2C peripherals also support the SMBus2.0 protocol. The SMBus protocol is similar to I2C and is mainly used in notebook computer battery management.

2. Pin distribution

The STM32 chip has multiple I2C peripherals, and their I2C communication signals are led to different GPIO pins, which must be configured to these designated pins when used.PB8 PB9 为重映射。

Three, EEPROM chip

The EEPROM chip model in the development board: AT24C02 . AT24C series are serial COMS type EEPROM introduced by ATMEL Company of the United States. The last two digits of the chip model indicate the chip capacity, for example, ATC24C02 is 2K. In the pin diagram, A0, A1, and A2 are device address pins, GND is ground, VCC is positive power supply, WP is write protection, SCL is serial clock line, and SDA is serial data line.

The WP pin in the EEPROM chip has a write protection function. When the pin level is high, data writing is prohibited. When the pin is low level, data can be written. We directly ground it and do not use the write protection function.

The address of the AT24Cxx device is as follows, the first four bits are fixed 1010, and A2~A0 are determined by the pin level . The AT24Cxx EEPROM Board module is grounded by default. A2~A0 are 000, the last bit R/W represents read and write operations. Since it is often I2C communication when connected with an address reader together to form an 8-bit direction, and when the R / W bit 0, it indicates a write direction, plus 7-bit address, a value 0xA0, which is often referred to "write address" I2C device; when the R / W bit 1, it indicates that the direction of reading, together with 7-bit address, a value 0xA1, which is often called "read address."

4. New construction

1. Open the STM32CubeMX software and click "New Project"

2. Choose MCU and package

3. Configure the clock
RCC settings, select HSE (external high-speed clock),

select Clock Configuration for Crystal/Ceramic Resonator (crystal oscillator/ceramic resonator) , configure the system clock SYSCLK to 72MHz,
modify the value of HCLK to 72, and press Enter. Automatically modify all configurations

4. It
is a very important step to configure the debug mode , otherwise the debugger
SYS setting will not be recognized after the first programming program , select Debug as Serial Wire

Five, I2C1

5.1 Parameter configuration

In the Connectivityselected I2C1settings, and select the I2Cinter-integrated circuit

I2C no modification to the default settings. Just note that I2C is the standard mode, and the I2C transmission rate (I2C Clock Speed) is 100KHz.

5.2 Generate code

Path item names and item input

selection of an application development environment IDE MDK-ARM V5

each peripheral generates a separate ’.c/.h’file
not hook: All initialization code is generated in main.c
checked: initialization code file generated in the associated peripheral. For example, the GPIO initialization code is generated in gpio.c.

Click GENERATE CODE to generate code

5.3 Add global variables

In main.c head Add the write address 0xA0, read address 0xA1, write buffer WriteBufferand read buffer ReadBuffer.

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

/* USER CODE BEGIN PV */
#define ADDR_24LCxx_Write 0xA0
#define ADDR_24LCxx_Read 0xA1
#define BufferSize 256
uint8_t WriteBuffer[BufferSize] = {
    
    0};
uint8_t ReadBuffer[BufferSize] = {
    
    0};
/* USER CODE END PV */

5.4 Add write and read functions

/**
  * @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_USART1_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  printf("\r\n***************I2C Example*******************************\r\n");
  uint8_t i;
  uint8_t j;
  for(i = 0; i < 256; i++)
  {
    
    
    WriteBuffer[i] = i;    /* WriteBuffer init */
    printf("0x%02X ", WriteBuffer[i]);
    if(i % 16 == 15)
    {
    
        
      printf("\n\r");
    }
  }
  /* wrinte date to EEPROM */
  for (j = 0; j < 32; j++)
  {
    
    
    if(HAL_I2C_Mem_Write(&hi2c1, ADDR_24LCxx_Write, 8*j, I2C_MEMADD_SIZE_8BIT, WriteBuffer+8*j, 8, 100) == HAL_OK)
    {
    
    
      printf("\r\n EEPROM 24C02 Write Test OK \r\n");
    }
    else
    {
    
    
      printf("\r\n EEPROM 24C02 Write Test False \r\n");
    }
  } 
  /* read date from EEPROM */
  HAL_I2C_Mem_Read(&hi2c1, ADDR_24LCxx_Read, 0, I2C_MEMADD_SIZE_8BIT, ReadBuffer, BufferSize, 1000);
  for(i = 0; i < 256; i++)
  {
    
    
    printf("0x%02X  ",ReadBuffer[i]);
    if(i%16 == 15)    
    {
    
    
      printf("\n\r");
    }
  }
    
  if(memcmp(WriteBuffer,ReadBuffer,BufferSize) == 0 ) /* check date */
  {
    
    
    printf("\r\n EEPROM 24C02 Read Test OK\r\n");
  }
  else
  {
    
    
    printf("\r\n EEPROM 24C02 Read Test False\r\n");
  }

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Initialize the write data cache in the program. Then call the HAL_I2C_Mem_Write()function to write data to the EEPROM. Judge whether the write operation is correct according to the function return value. The description of the memory write function can be found in I2C.

  • The first parameter is the I2C operation handle.
  • The second parameter is the EEPROM write operation device address.
  • The third parameter is the memory address.
  • The fourth parameter is the memory address length, and the EEPROM memory length is 8bit.
  • The fifth parameter is the starting address of the data buffer.
  • The sixth parameter is the size of the transmitted data.AT24C02 型号的芯片页写入时序最多可以一次 发送 8 个数据(即 n = 8 ),该值也称为页大小,某些型号的芯片每个页写入时序最多可传输 16 个数据。
  • The seventh parameter is the operation timeout period.
/**
  * @brief  Write an amount of data in blocking mode to a specific memory address
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address value
  *         in datasheet must be shifted to the left before calling the interface
  * @param  MemAddress Internal memory address
  * @param  MemAddSize Size of internal memory address
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
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)


Call the HAL_I2C_Mem_Read()function to read the data in EEPROM have just written. HAL_I2C_Mem_Read()The function is described as follows.

  • The first parameter is the I2C operation handle.
  • The second parameter is the EEPROM read operation device address.
  • The third parameter is the memory address.
  • The fourth parameter is the length of the memory address.
  • The fifth parameter is the starting address of reading data storage.
  • The sixth parameter is the size of the transmitted data.
  • The seventh parameter is the operation timeout period.
/**
  * @brief  Read an amount of data in blocking mode from a specific memory address
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address value
  *         in datasheet must be shifted to the left before calling the interface
  * @param  MemAddress Internal memory address
  * @param  MemAddSize Size of internal memory address
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
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)

Finally, the program calls the memcmp()function to determine whether two cache read and write data consistency. memcmp()Is more memory regions are equal, which is the standard library function, the main.cadd front string.hheader.

5.5 View print

Serial port printing function view STM32CubeMX study notes (6)-USART serial port use

5.6 Comparison of HAL library and standard library code

STM32CubeMX uses the code generated by the HAL library:

/**
  * @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 = 100000;
  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 */
}

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);
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);

Use STM32 standard library code:

/**
  * @brief  I2C I/O配置
  * @param  无
  * @retval 无
  */
static void I2C_GPIO_Config(void)
{
    
    
  GPIO_InitTypeDef  GPIO_InitStructure; 

	/* 使能与 I2C 有关的时钟 */
	EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );
	EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );
	
    
  /* I2C_SCL、I2C_SDA*/
  GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	       // 开漏输出
  GPIO_Init(EEPROM_I2C_SCL_PORT, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	       // 开漏输出
  GPIO_Init(EEPROM_I2C_SDA_PORT, &GPIO_InitStructure);		
}

/**
  * @brief  I2C 工作模式配置
  * @param  无
  * @retval 无
  */
static void I2C_Mode_Config(void)
{
    
    
  I2C_InitTypeDef  I2C_InitStructure; 

  /* I2C 配置 */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	
	/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	
  I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; 
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
	 
	/* I2C的寻址模式 */
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	
	/* 通信速率 */
  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
  
	/* I2C 初始化 */
  I2C_Init(EEPROM_I2Cx, &I2C_InitStructure);
  
	/* 使能 I2C */
  I2C_Cmd(EEPROM_I2Cx, ENABLE);   
}

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);

Six, matters needing attention

User code to be added to USER CODE BEGIN Nand USER CODE END Nbetween, otherwise the next use after STM32CubeMX regenerate the code, it will be deleted.


Written by Leung on January 26, 2021

• Reference: STM32CubeMX Series Tutorial 9: Inter-Integrated Circuit (I2C)
    [STM32Cube_13] Use hardware I2C to read and write EEPROM (AT24C02)

Guess you like

Origin blog.csdn.net/qq_36347513/article/details/113180162