STM32F103 realizes temperature and humidity (AHT20) collection through IIC protocol

STM32F103 realizes temperature and humidity (AHT20) collection through IIC protocol

Article directory

  • STM32F103 realizes temperature and humidity (AHT20) collection through IIC protocol
  • 1. IIC Agreement
    • 1. Introduction to IIC protocol
    • 2. Physical layer and protocol layer
    • 3. Software IIC and hardware IIC
  • 2. Temperature and humidity collection

1. IIC protocol

1. Introduction to IIC protocol

The IIC communication protocol (Inter-Integrated Circuit) was developed by Phililps Company. Because it has fewer pins, simple hardware implementation, strong scalability, and does not require external transceiver devices for communication protocols such as USART and CAN, it is now widely used in Communication between multiple integrated circuits (ICs) within the system.

2. Physical layer and protocol layer

2.1Physical layer

IIC is a bus that supports devices. Can connect multiple IIC communication devices, supporting multiple communication hosts and multiple communication slaves. For the IIC bus, only two bus lines are used, a bidirectional serial data line (SDA) and a serial clock line (SCL).
Common connection methods for IIC communication equipment:

2.2 Protocol layer
The protocol layer mainly defines the start and stop signals of communication, data validity, response, arbitration, clock synchronization and address broadcast, etc.
Communication start and end signals:

Data validity:

IIC uses the SDA signal line to transmit data and the SCL signal line for data synchronization. The SDA data line transfers one bit of data on each clock cycle of SCL. During transmission, when SCL is high level, the data represented by SDA is valid, that is, when SDA is high level, it represents data “1”, and when it is low level, it represents data “0”. When SCL is low, the data in SDA is invalid. Generally, SDA switches levels at this time to prepare for the next data representation.
Read and write data:
Read data
? If the configured direction transmission bit is the “read data” direction, that is, the situation in the second picture, after broadcasting the address and receiving the response signal, the slave begins to return data (DATA) to the host, and the data packet size is also 8 bits , every time the slave sends a piece of data, it will wait for the host’s response signal (ACK). Repeating this process, it can return N pieces of data, and there is no size limit for this N. When the host wants to stop receiving data, it returns a non-acknowledge signal (NACK) to the slave, and the slave automatically stops data transmission.
write data
? If the configured direction transmission bit is the “write data” direction, that is, the situation in the first picture, after broadcasting the address and receiving the response signal, the host begins to officially transmit data (DATA) to the slave, and the size of the data packet is 8 bit, every time the master sends a byte of data, it must wait for the slave’s response signal (ACK). Repeating this process, it can transmit N data to the slave. There is no size limit for this N. When the data transmission ends, the master sends a stop transmission signal§ to the slave, indicating that no more data will be transmitted.

3. Software IIC and hardware IIC

? If you want to control STM32 to generate IIC communication, you can use software simulation or hardware IIC.
Hardware IIC directly uses peripherals to control pins, which can reduce the burden on the CPU. However, when using hardware IIC, certain fixed pins must be used as SCL and SDA, while software simulation IIC can use any GPIO pin, which is relatively flexible. In this development board, because the STM32RCT6 chip has fewer pins and tight resources, it is inconvenient to use the pins specified by the hardware IIC to connect to external devices (EEPROM memory chips) when designing hardware, so only software simulation can be used in the control program. IIC way.

3.1 Software simulation
? The so-called software simulation means directly using the CPU core to control the GPIO output high and low levels according to the requirements of the IIC protocol. For example, when controlling to generate the start signal of IIC, first control the GPIO pin as the SCL line to output a high level, then control the GPIO pin as the SDA line to complete the switching from high level to low level during this period, and finally control the Control the SCL line to switch to low level, thus outputting a standard IIC start signal.

3.2 Hardware IIC
Hardware IIC refers to the direct use of hardware IIC peripherals in the STM32 chip. The hardware IIC peripherals are similar to the USART serial port peripherals. As long as the corresponding registers are configured, the peripherals will generate the timing of the standard serial port protocol. Using its IIC peripherals, you can easily generate IIC protocol communication through peripheral registers. For example, after initializing the IIC peripherals, you only need to set a certain register bit to 1, and then the peripherals will control the corresponding SCL and SDA lines automatically. Generates the IIC start signal without requiring the core to directly control the pin’s level.

2. Temperature and humidity collection

1.Create project

After selecting STM32F103C8T6, configure the parameters
Configure GPIO port

Configure rcc

Configure sys

Other parameters



clock

Open the keil file in the generated file
Open the main.c file
Replace the code in main.c with

/* USER CODE BEGIN Header */
/**
  *************************************************** ****************************
  * @file: main.c
  * @brief: Main program body
  *************************************************** ****************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  *************************************************** ****************************
  */
/* USER CODE END Header */
/* Includes ----------------------------------------------- ------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"

/* Private includes -------------------------------------------------- ----------*/
/* USER CODE BEGIN Includes */
#include<stdio.h>
#include "AHT20-21_DEMO_V1_3.h"
/* USER CODE END Includes */

/* Private typedef ----------------------------------------------- -------------*/
/* USER CODE BEGIN PTD */
int fputc(int ch,FILE *f)
{<!-- -->
    HAL_UART_Transmit( & amp;huart1,(uint8_t *) & amp;ch,1,0xFFFF);
//
while(__HAL_UART_GET_FLAG( & amp;huart1,UART_FLAG_TC)!=SET){<!-- -->
}

    return ch;
}
/* 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 -------------------------------------------------- -----------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes ------------------------------------------------ --*/
void SystemClock_Config(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 */
uint32_t CT_data[2]={<!-- -->0,0};
volatile int c1,t1;
Delay_1ms(500);
  /* 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_DMA_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
\t
  /* USER CODE BEGIN 2 */
  AHT20_Init();
Delay_1ms(500);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {<!-- -->
    /* USER CODE END WHILE */
//AHT20_Read_CTdata(CT_data); //?CRC,AHT20 1S?
AHT20_Read_CTdata_crc(CT_data); //crc?,AHT20?
\t

c1 = CT_data[0]*1000/1024/1024; //?c1(?10?)
t1 = CT_data[1]*2000/1024/1024-500;//?t1(?10?)
printf("");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
printf("\r\
");
HAL_Delay(1000);
printf(":%d%d.%d",t1/100,(t1/10) ,t1 );
printf(":%d%d.%d",c1/100,(c1/10) ,c1 );
printf("\r\
");
printf("");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
HAL_Delay(100);
printf(".");
printf("\r\
");
HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* 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_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig( & amp;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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig( & amp;RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {<!-- -->
    Error_Handler();
  }
}

/* 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\
", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Add the following two files to the file

In the .c file, replace the code with

/************************************************/
/*@: */
/*@:? */
/*@:V1.2 */
/************************************************/
//#include "main.h"
#include "AHT20-21_DEMO_V1_3.h"
#include "gpio.h"
#include "i2c.h"


void Delay_N10us(uint32_t t)//
{<!-- -->
  uint32_t k;

   while(t--)
  {<!-- -->
    for (k = 0; k < 2; k + + );//110
  }
}

void SensorDelay_us(uint32_t t)//
{<!-- -->
\t\t
for(t = t-2; t>0; t--)
{<!-- -->
Delay_N10us(1);
}
}

void Delay_4us(void) //
{<!-- -->
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
}
void Delay_5us(void) //
{<!-- -->
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);

}

void Delay_1ms(uint32_t t) //
{<!-- -->
   while(t--)
  {<!-- -->
    SensorDelay_us(1000);//1ms
  }
}


//void AHT20_Clock_Init(void) //
//{<!-- -->
// RCC_APB2PeriphClockCmd(CC_APB2Periph_GPIOB,ENABLE);
//}

void SDA_Pin_Output_High(void) //?PB7? , ?, PB7I2C?SDA
{<!-- -->
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, & amp; GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
}

void SDA_Pin_Output_Low(void) //?P7? ?
{<!-- -->
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, & amp; GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);
}

void SDA_Pin_IN_FLOATING(void) //SDA?
{<!-- -->
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init( GPIOB, & amp;GPIO_InitStruct);
}


void SCL_Pin_Output_High(void) //SCL?,P14I2C?SCL
{<!-- -->
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
}

void SCL_Pin_Output_Low(void) //SCL?
{<!-- -->
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
}

void Init_I2C_Sensor_Port(void) //?I2C,
{<!-- -->
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, & amp; GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);

\t
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, & amp; GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
\t
}
void I2C_Start(void) //I2CSTART
{<!-- -->
SDA_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_Low();
SensorDelay_us(8);
}


void AHT20_WR_Byte(uint8_t Byte) //?AHT20?
{<!-- -->
uint8_t Data,N,i;
Data=Byte;
i = 0x80;
for(N=0;N<8;N + + )
{<!-- -->
SCL_Pin_Output_Low();
Delay_4us();
if(i&Data)
{<!-- -->
SDA_Pin_Output_High();
}
else
{<!-- -->
SDA_Pin_Output_Low();
}
\t\t\t
    SCL_Pin_Output_High();
Delay_4us();
Data <<= 1;
\t\t 
}
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
}


uint8_t AHT20_RD_Byte(void)//?AHT20
{<!-- -->
uint8_t Byte,i,a;
Byte = 0;
SCL_Pin_Output_Low();
\t
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
\t
for(i=0;i<8;i + + )
{<!-- -->
    SCL_Pin_Output_High();
\t\t
Delay_5us();
a=0;
\t\t
//if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)) a=1;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)) a=1;
Byte = (Byte<<1)|a;
\t\t
//SCL_Pin_Output_Low();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
Delay_5us();
}
  SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
return Byte;
}


uint8_t Receive_ACK(void) //?AHT20ACK
{<!-- -->
uint16_t CNT;
CNT = 0;
SCL_Pin_Output_Low();
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
while((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)) & amp; & amp; CNT < 100)
CNT + + ;
if(CNT == 100)
{<!-- -->
return 0;
}
 SCL_Pin_Output_Low();
SensorDelay_us(8);
return 1;
}

void Send_ACK(void) //ACK
{<!-- -->
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
}

void Send_NOT_ACK(void) //ACK
{<!-- -->
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_Low();
SensorDelay_us(8);
    SDA_Pin_Output_Low();
SensorDelay_us(8);
}

void Stop_I2C(void) //
{<!-- -->
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SDA_Pin_Output_High();
SensorDelay_us(8);
}

uint8_t AHT20_Read_Status(void)//AHT20
{<!-- -->

uint8_t Byte_first;
I2C_Start();
AHT20_WR_Byte(0x71);
Receive_ACK();
Byte_first = AHT20_RD_Byte();
Send_NOT_ACK();
Stop_I2C();
return Byte_first;
}

uint8_t AHT20_Read_Cal_Enable(void) //cal enable
{<!-- -->
uint8_t val = 0;//ret = 0,
  val = AHT20_Read_Status();
if((val & amp; 0x68)==0x08)
return 1;
   else return 0;
 }

void AHT20_SendAC(void) //?AHT20AC
{<!-- -->

I2C_Start();
AHT20_WR_Byte(0x70);
Receive_ACK();
AHT20_WR_Byte(0xac);//0xAC
Receive_ACK();
AHT20_WR_Byte(0x33);
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();

}

//CRC:CRC8/MAXIM
//?:X8 + X5 + X4 + 1
//Poly:0011 0001 0x31
//? 1000 1100 0x8c
//C:
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num)
{<!-- -->
uint8_t i;
uint8_t byte;
uint8_t crc=0xFF;
  for(byte=0; byte<Num; byte + + )
  {<!-- -->
    crc^=(message[byte]);
    for(i=8;i>0;--i)
    {<!-- -->
      if(crc & amp;0x80) crc=(crc<<1)^0x31;
      else crc=(crc<<1);
    }
  }
        return crc;
}

void AHT20_Read_CTdata(uint32_t *ct) //CRC,AHT20
{<!-- -->
volatile uint8_t Byte_1th=0;
volatile uint8_t Byte_2th=0;
volatile uint8_t Byte_3th=0;
volatile uint8_t Byte_4th=0;
volatile uint8_t Byte_5th=0;
volatile uint8_t Byte_6th=0;
uint32_t RetuData = 0;
uint16_t cnt = 0;
AHT20_SendAC();//?AHT10AC
Delay_1ms(80);//80ms
    cnt = 0;
while(((AHT20_Read_Status() &0x80)==0x80))//bit[7]?0,?1,
{<!-- -->
SensorDelay_us(1508);
if(cnt + + >=100)
{<!-- -->
break;
}
}
I2C_Start();
AHT20_WR_Byte(0x71);
Receive_ACK();
Byte_1th = AHT20_RD_Byte();//?,0x98,,bit[7]?1;?0x1C,0x0C,0x08 ?,bit[7]?0
Send_ACK();
Byte_2th = AHT20_RD_Byte();//
Send_ACK();
Byte_3th = AHT20_RD_Byte();//
Send_ACK();
Byte_4th = AHT20_RD_Byte();///
Send_ACK();
Byte_5th = AHT20_RD_Byte();//
Send_ACK();
Byte_6th = AHT20_RD_Byte();//
Send_NOT_ACK();
Stop_I2C();

RetuData = (RetuData|Byte_2th)<<8;
RetuData = (RetuData|Byte_3th)<<8;
RetuData = (RetuData|Byte_4th);
RetuData =RetuData >>4;
ct[0] = RetuData;//
RetuData = 0;
RetuData = (RetuData|Byte_4th)<<8;
RetuData = (RetuData|Byte_5th)<<8;
RetuData = (RetuData|Byte_6th);
RetuData = RetuData &0xfffff;
ct[1] =RetuData; //

}


void AHT20_Read_CTdata_crc(uint32_t *ct) //CRC?,AHT20
{<!-- -->
volatile uint8_t Byte_1th=0;
volatile uint8_t Byte_2th=0;
volatile uint8_t Byte_3th=0;
volatile uint8_t Byte_4th=0;
volatile uint8_t Byte_5th=0;
volatile uint8_t Byte_6th=0;
volatile uint8_t Byte_7th=0;
uint32_t RetuData = 0;
uint16_t cnt = 0;
// uint8_t CRCDATA=0;
uint8_t CTDATA[6]={<!-- -->0};//CRC
\t
AHT20_SendAC();//?AHT10AC
Delay_1ms(80);//80ms
    cnt = 0;
while(((AHT20_Read_Status() &0x80)==0x80))//bit[7]?0,?1,
{<!-- -->
SensorDelay_us(1508);
if(cnt + + >=100)
{<!-- -->
break;
}
}
\t
I2C_Start();

AHT20_WR_Byte(0x71);
Receive_ACK();
CTDATA[0]=Byte_1th = AHT20_RD_Byte();//?,0x98,,bit[7]?1;?0x1C,0x0C, 0x08?,bit[7]?0
Send_ACK();
CTDATA[1]=Byte_2th = AHT20_RD_Byte();//
Send_ACK();
CTDATA[2]=Byte_3th = AHT20_RD_Byte();//
Send_ACK();
CTDATA[3]=Byte_4th = AHT20_RD_Byte();///
Send_ACK();
CTDATA[4]=Byte_5th = AHT20_RD_Byte();//
Send_ACK();
CTDATA[5]=Byte_6th = AHT20_RD_Byte();//
Send_ACK();
Byte_7th = AHT20_RD_Byte();//CRC
Send_NOT_ACK(); //: NAK
Stop_I2C();
\t
if(Calc_CRC8(CTDATA,6)==Byte_7th)
{<!-- -->
RetuData = (RetuData|Byte_2th)<<8;
RetuData = (RetuData|Byte_3th)<<8;
RetuData = (RetuData|Byte_4th);
RetuData =RetuData >>4;
ct[0] = RetuData;//
RetuData = 0;
RetuData = (RetuData|Byte_4th)<<8;
RetuData = (RetuData|Byte_5th)<<8;
RetuData = (RetuData|Byte_6th);
RetuData = RetuData &0xfffff;
ct[1] =RetuData; //
\t\t
}
else
{<!-- -->
ct[0]=0x00;
ct[1]=0x00;//?,
}//CRC
}


void AHT20_Init(void) //?AHT20
{<!-- -->
Init_I2C_Sensor_Port();
I2C_Start();
AHT20_WR_Byte(0x70);
Receive_ACK();
AHT20_WR_Byte(0xa8);//0xA8NOR
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();

Delay_1ms(10);//10ms

I2C_Start();
AHT20_WR_Byte(0x70);
Receive_ACK();
AHT20_WR_Byte(0xbe);//0xBE?,AHT20?0xBE, AHT10?0xE1
Receive_ACK();
AHT20_WR_Byte(0x08);//?bit[3]?1,?
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();
Delay_1ms(10);//10ms
}
void JH_Reset_REG(uint8_t addr)
{<!-- -->
\t
uint8_t Byte_first,Byte_second,Byte_third;
I2C_Start();
AHT20_WR_Byte(0x70);//?0x70
Receive_ACK();
AHT20_WR_Byte(addr);
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();

Delay_1ms(5);//5ms
I2C_Start();
AHT20_WR_Byte(0x71);//
Receive_ACK();
Byte_first = AHT20_RD_Byte();
Send_ACK();
Byte_second = AHT20_RD_Byte();
Send_ACK();
Byte_third = AHT20_RD_Byte();
Send_NOT_ACK();
Stop_I2C();
\t
  Delay_1ms(10);//10ms
I2C_Start();
AHT20_WR_Byte(0x70);///
Receive_ACK();
AHT20_WR_Byte(0xB0|addr);//?
Receive_ACK();
AHT20_WR_Byte(Byte_second);
Receive_ACK();
AHT20_WR_Byte(Byte_third);
Receive_ACK();
Stop_I2C();
\t
Byte_second=0x00;
Byte_third =0x00;
}

void AHT20_Start_Init(void)
{<!-- -->
JH_Reset_REG(0x1b);
JH_Reset_REG(0x1c);
JH_Reset_REG(0x1e);
}

In the .h file replace the code with

#ifndef _AHT20_DEMO_
#define _AHT20_DEMO_

#include "main.h"

void Delay_N10us(uint32_t t);//
void SensorDelay_us(uint32_t t);//
void Delay_4us(void); //
void Delay_5us(void); //
void Delay_1ms(uint32_t t);
void AHT20_Clock_Init(void); //
void SDA_Pin_Output_High(void) ; //?PB15? , ?, PB15I2C?SDA
void SDA_Pin_Output_Low(void); //?P15? ?
void SDA_Pin_IN_FLOATING(void); //SDA?
void SCL_Pin_Output_High(void); //SCL?,P14I2C?SCL
void SCL_Pin_Output_Low(void); //SCL?
void Init_I2C_Sensor_Port(void); //?I2C,
void I2C_Start(void); //I2CSTART
void AHT20_WR_Byte(uint8_t Byte); //?AHT20?
uint8_t AHT20_RD_Byte(void);//?AHT20
uint8_t Receive_ACK(void); //?AHT20ACK
void Send_ACK(void) ; //ACK
void Send_NOT_ACK(void); //?ACK
void Stop_I2C(void); //
uint8_t AHT20_Read_Status(void);//AHT20
uint8_t AHT20_Read_Cal_Enable(void); //cal enable
void AHT20_SendAC(void); //?AHT20AC
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num);
void AHT20_Read_CTdata(uint32_t *ct); //CRC,AHT20
void AHT20_Read_CTdata_crc(uint32_t *ct); //CRC?,AHT20
void AHT20_Init(void); //?AHT20
void JH_Reset_REG(uint8_t addr);///?
void AHT20_Start_Init(void);///?
#endif

Connect the line and open the serial port assistant