• The last:【STM32Cube_14】 Use hardware I2C to read and write ambient light intensity sensor (BH1750)

For a better reading experience, please go:Mculover666’s personal blog.

This detailed record of how to use STM32CubeMX configuration OF STM32L431RCT6 hardware I2C peripherals, read the SHT30 temperature and humidity sensor data and send through the serial port.

1. Preparation

Hardware preparation

  • Development board First needs to prepare a development board, here I prepared the development board of STM32L4 (BearPi) :

  • SHT30 T/H sensor The SHT30 t/H sensor is a fully calibrated, current, digital output sensor with temperature compensation. It supports a wide voltage range of 2.4V to 5.5V and uses an IIC interface for communication. The maximum speed is up to 1M and two user-optional addresses are available. It also comes in an 8-pin DFN ultra-small package, pictured here:

The schematic diagram of the SHT30 is as follows:

Software to prepare

  • Keil-mdk and the corresponding chip package need to be installed in order to compile and download the generated code;
  • Prepare a serial debugging assistant, the one I used hereSerial Port Utility;

Keil MDK and Serial Port Utility installation packages are available at the end of this article.

2. Generate MDK projects

Select the chip model

Open STM32CubeMX, open MCU selector:

Search for and select the chipSTM32L431RCT6:

Configuring the Clock Source

  • If you choose to use an external high speed clock (HSE), you need to configure RCC in the System Core;
  • If you use the default internal clock (HSI), you can skip this step.

Here I use the external clock:

Configure a serial port

Bear Pai developed onboard ST-link and virtual a serial port, the schematic diagram is as follows:

Here, I switch the switch to at-MCU mode to connect the PC serial port with USART1.

Next, configure USART1:

Configure an I2C interface

View the schematic of the Bear PI E53 interface:

Configure I2C interface 1:

Configuring the Clock Tree

The maximum main frequency of STM32L4 is 80M, so PLL is configured and finally enabledHCLK = 80MhzYou can:

Build project Settings

Code generation Settings

Finally set to generate a separate initialization file:

The generated code

Click on theGENERATE CODEMdk-v5 project can be generated:

3. Write, compile and download user code in MDK

Redirect the printf() function

STM32Cube_09 redirects printf function to serial port output.

Fixed a BUG in the I2C initialization code

4. Write SHT30 driver program

Refer to SHT30 data manual. PDF for programming.

Macro defines SHT30 device address

The device address of SHT30 is determined by the high and low level of the ADDR port:

Note that 8 bits of data are given in the data manual, and only the lower 7 bits are used as addresses. Combined with the schematic diagram, it can be defined as follows:

/* ADDR Pin Conect to VSS */

#define	SHT30_ADDR_WRITE	0x44<<1         / / 10001000
#define	SHT30_ADDR_READ		(0x44<<1)+1	    / / 10001011
Copy the code

Enumerates SHT30 command list

Refer to the data sheet for the following enumeration definitions in the sht30_i2C_drv.h header:

typedef enum
{
    /* Software reset command */

    SOFT_RESET_CMD = 0x30A2.Repeatability_CS_CMD CS: Clock stretching */
    HIGH_ENABLED_CMD    = 0x2C06,
    MEDIUM_ENABLED_CMD  = 0x2C0D,
    LOW_ENABLED_CMD     = 0x2C10,
    HIGH_DISABLED_CMD   = 0x2400,
    MEDIUM_DISABLED_CMD = 0x240B,
    LOW_DISABLED_CMD    = 0x2416.Repeatability_MPS_CMD MPS: measurement per second */
    HIGH_0_5_CMD   = 0x2032,
    MEDIUM_0_5_CMD = 0x2024,
    LOW_0_5_CMD    = 0x202F,
    HIGH_1_CMD     = 0x2130,
    MEDIUM_1_CMD   = 0x2126,
    LOW_1_CMD      = 0x212D,
    HIGH_2_CMD     = 0x2236,
    MEDIUM_2_CMD   = 0x2220,
    LOW_2_CMD      = 0x222B,
    HIGH_4_CMD     = 0x2334,
    MEDIUM_4_CMD   = 0x2322,
    LOW_4_CMD      = 0x2329,
    HIGH_10_CMD    = 0x2737,
    MEDIUM_10_CMD  = 0x2721,
    LOW_10_CMD     = 0x272A./* Cycle measurement mode read data command */
	READOUT_FOR_PERIODIC_MODE = 0xE000,
} SHT30_CMD;
Copy the code

Send command function

/** * @brief sends an instruction to SHT30 (16bit) * @param CMD -- SHT30 instruction (defined by enumeration in SHT30_MODE) * @retval returns HAL_OK */ on success
static uint8_t	SHT30_Send_Cmd(SHT30_CMD cmd)
{
    uint8_t cmd_buffer[2];
    cmd_buffer[0] = cmd >> 8;
    cmd_buffer[1] = cmd;
    return HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR_WRITE, (uint8_t* cmd_buffer, 2.0xFFFF);
}
Copy the code

The reset function

/** * @brief reset SHT30 * @param None * @retval None */
void SHT30_reset(void)
{
    SHT30_Send_Cmd(SOFT_RESET_CMD);
    HAL_Delay(20);
}
Copy the code

SHT30 working mode initialization function (periodic measurement mode)

/** * @brief Initializes SHT30 * @param None * @retval Returns HAL_OK * @note periodic measurement mode */
uint8_t SHT30_Init(void)
{
    return SHT30_Send_Cmd(MEDIUM_2_CMD);
}
Copy the code

Read data once from SHTY30 (in periodic measurement mode)

The timing sequence of reading a data in periodic measurement mode can be obtained from the SHT30 data manual, as shown in the figure:

It can be seen from the time sequence that the command to read data should be sent first, and then 6 bytes of data should be received. The program is written as follows:

/** * @brief read data once from SHT30 * @param DAT -- store read data address (6-byte array) * @retval succeeded -- return HAL_OK */
uint8_t SHT30_Read_Dat(uint8_t* dat)
{
	SHT30_Send_Cmd(READOUT_FOR_PERIODIC_MODE);
	return HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR_READ, dat, 6.0xFFFF);
}
Copy the code

Verify and parse temperature and humidity values from received data

According to the data manual, SHT30 sends 8-CRC check codes after temperature data and humidity data respectively to ensure data reliability.

For more information on CRC validation, please refer to my other blog post: How to understand CRC validation in plain English and implement it in C.

The crC-8 check procedure is as follows:

#define CRC8_POLYNOMIAL 0x31

uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
    uint8_t  remainder;	    / / remainder
    uint8_t  i = 0, j = 0;  // Loop variables

    /* Initialize */
    remainder = initial_value;

    for(j = 0; j < 2; j++) { remainder ^= message[j];/* Counting */ from the highest bit
        for (i = 0; i < 8; i++)
        {
            if (remainder & 0x80)
            {
                remainder = (remainder << 1)^CRC8_POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1); }}}/* Returns the computed CRC code */
    return remainder;
}
Copy the code

The formulas for calculating temperature and humidity values are given in the data manual, as shown in the figure below:

Next, write a function that parses the data:

/** * @brief perform CRC check on 6 bytes of data received by SHT30 and convert them to temperature and humidity values * @param DAT -- store the address of received data (6 bytes array) * @retval successful check -- return 0 * failed check -- return 1, Set the temperature and humidity to 0 */
uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
{
	uint16_t recv_temperature = 0;
	uint16_t recv_humidity = 0;
	
	/* Verify that temperature data and humidity data are received correctly */
	if(CheckCrc8(dat, 0xFF) != dat[2] || CheckCrc8(&dat[3].0xFF) != dat[5])
		return 1;
	
	/* Convert temperature data */
	recv_temperature = ((uint16_t)dat[0] < <8)|dat[1];
	*temperature = - 45 + 175* ((float)recv_temperature/65535);
	
	/* Convert humidity data */
	recv_humidity = ((uint16_t)dat[3] < <8)|dat[4];
	*humidity = 100 * ((float)recv_humidity / 65535);
	
	return 0;
}
Copy the code

5. Test SHT30 driver

To test the driver in the main function, add the following code to main.c:

#include <stdio.h>
#include "sht30_i2c_drv.h"

int main(void)
{
    /* USER CODE BEGIN 1 */
    uint8_t recv_dat[6] = {0};
    float temperature = 0.0;
    float humidity = 0.0;
    /* USER CODE END 1 */

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_I2C1_Init();
    MX_USART1_UART_Init();

    /* USER CODE BEGIN 2 */
    SHT30_Reset();
    if(SHT30_Init() == HAL_OK)
        printf("sht30 init ok.\n");
    else
        printf("sht30 init fail.\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		
    /* USER CODE BEGIN 3 */
		HAL_Delay(1000);
		if(SHT30_Read_Dat(recv_dat) == HAL_OK)
		{
			if(SHT30_Dat_To_Float(recv_dat, &temperature, &humidity)==0)
			{
				printf("temperature = %f, humidity = %f\n", temperature, humidity);
			}
			else
			{
				printf("crc check fail.\n"); }}else
		{
			printf("read data from sht30 fail.\n"); }}/* USER CODE END 3 */
}
Copy the code

The test results are shown as follows:

So far, we have learned how to use the hardware IIC interface to read the temperature and humidity sensor data and use the software CRC check (SHT30). The next section describes how to use the hardware CRC check (SHT30) data.

  • The last:【STM32Cube_14】 Use hardware I2C to read and write ambient light intensity sensor (BH1750)
  • Next up:【STM32Cube_16】 Use hardware CRC check data (SHT30 as an example).

For more exciting articles and resources, please pay attention to my wechat official number: “McUlover666”.