Use dht20 to implement temperature and humidity detection in stm32

dht20 hardware and environment i2c

I2C (Inter-Integrated Circuit) is a serial communication protocol used to communicate between electronic devices. It consists of two lines: clock line (SCL, Serial Clock) and data line (SDA, Serial Data). The I2C protocol uses a master-slave structure, in which one device acts as the master device and is responsible for initiating and controlling communication, and other devices act as slave devices to respond to the master device’s commands.

In I2C communication, the master device generates a clock signal to synchronize the communication process and sends and receives data through the data line. After the master device initiates communication, it selects the slave device address to communicate with and sends commands or data to it. The slave device performs the corresponding operation after receiving the command and returns the result to the master device. This communication method is suitable for short-distance connections and is often used to connect microcontrollers, sensors, memory and other peripheral devices.

There is no difference between dht20 and aht20. They are both Auson products, so you can choose them yourself.

Connect the SCL pin of the AHT20 sensor to the I2C clock line pin of the STM32 (usually labeled SCL, SCK or I2C_SCL) and the SDA pin to the I2C data line pin of the STM32 (usually labeled SDA, SDI or I2C_SDA) . There are also vcc and grund that you can connect accordingly.

This is the instruction manual from the Orson official website.
Our SDA and SCL use PB7 and PB6. Just connect them yourself.
After the sensor reads the corresponding data, we also use DMA to communicate to the PC.
Our temperature and humidity are continuously sent in the loop. If there is, we can also set an interrupt service function to implement other functions. There is also processing of i2c communication initialization.

We use keil 5 for operation. stm32f103c8t6 minimum development board.

First create a project containing the regular stm32 firmware library to facilitate environment configuration.
Then write it.
main.c

#include "Delay.h"
#include "usart.h"
#include "bsp_i2c.h"


int main(void)
{<!-- -->
\t    
uart_init(115200);
IIC_Init();
while(1)
{<!-- -->
printf("Start testing temperature and humidity");
read_AHT20_once();
delay_ms(1500);
  }
}

The next one is usart.c

#include "sys.h"
#include "usart.h"






#if SYSTEM_SUPPORT_UCOS
#include "includes.h"
#endif

  
#if 1
#pragma import(__use_no_semihosting)
            
struct __FILE
{<!-- -->
int handle;

};

FILE __stdout;
  
void _sys_exit(int x)
{<!-- -->
x = x;
}

int fputc(int ch, FILE *f)
{<!-- -->
while((USART1->SR & amp;0X40)==0);
    USART1->DR = (u8) ch;
return ch;
}
#endif


 
#if EN_USART1_RX
\t
u8 USART_RX_BUF[USART_REC_LEN];

u16 USART_RX_STA=0;
  
void uart_init(u32 bound){<!-- -->
  
  GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
\t 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, & amp;GPIO_InitStructure);
   
    //USART1_RX PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, & amp;GPIO_InitStructure);

   //Usart1 NVIC

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( & amp;NVIC_InitStructure);
  
   //USAR

USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART1, & amp;USART_InitStructure);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART1, ENABLE);

}



void USART1_IRQHandler(void)
{<!-- -->
u8 Res;
#ifdef OS_TICKS_PER_SEC
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{<!-- -->
Res =USART_ReceiveData(USART1);//(USART1->DR);
\t\t
if((USART_RX_STA &0x8000)==0)
{<!-- -->
if(USART_RX_STA &0x4000)
{<!-- -->
if(Res!=0x0a)USART_RX_STA=0;
else USART_RX_STA|=0x8000;
}
else
{<!-- -->
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{<!-- -->
USART_RX_BUF[USART_RX_STA & amp;0X3FFF]=Res;
USART_RX_STA + + ;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
}
}
}
     }
#ifdef OS_TICKS_PER_SEC
OSIntExit();
#endif
}
#endif


The next one is usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"




#define USART_REC_LEN 200
#define EN_USART1_RX 1
\t  \t
extern u8 USART_RX_BUF[USART_REC_LEN];
extern u16 USART_RX_STA;

void uart_init(u32 bound);
#endif


Nextbsp_i2c.c

#include "bsp_i2c.h"
#include "delay.h"

uint8_t ack_status=0;
uint8_t readByte[6];
uint8_t AHT20_status=0;

uint32_t H1=0; //Humility
uint32_t T1=0; //Temperature

uint8_t AHT20_OutData[4];
uint8_t AHT20sendOutData[10] = {<!-- -->0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

void IIC_Init(void)
{<!-- -->
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
\t   
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, & amp;GPIO_InitStructure);
 
IIC_SCL=1;
IIC_SDA=1;
 
}

void IIC_Start(void)
{<!-- -->
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
 IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;
}

void IIC_Stop(void)
{<!-- -->
SDA_OUT();
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 delay_us(4);
IIC_SCL=1;
IIC_SDA=1;
delay_us(4);
}

u8 IIC_Wait_Ack(void)
{<!-- -->
u8 ucErrTime=0;
SDA_IN();
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{<!-- -->
ucErrTime + + ;
if(ucErrTime>250)
{<!-- -->
IIC_Stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}

void IIC_Ack(void)
{<!-- -->
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
\t    
void IIC_NAck(void)
{<!-- -->
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
\t\t  
void IIC_Send_Byte(u8 txd)
{<!-- -->
    u8t;
SDA_OUT();
    IIC_SCL=0;
    for(t=0;t<8;t + + )
    {<!-- -->
        IIC_SDA=(txd & amp;0x80)>>7;
        txd<<=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
    }
}

u8 IIC_Read_Byte(unsigned char ack)
{<!-- -->
unsigned char i,receive=0;
SDA_IN();
  for(i=0;i<8;i + + )
{<!-- -->
    IIC_SCL=0;
    delay_us(2);
IIC_SCL=1;
    receive<<=1;
    if(READ_SDA)receive + + ;
delay_us(1);
  }
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
 
void IIC_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)
{<!-- -->
IIC_Start();
\t
if(device_addr==0xA0)
IIC_Send_Byte(0xA0 + ((addr/256)<<1));
else
IIC_Send_Byte(device_addr);
IIC_Wait_Ack();
IIC_Send_Byte(addr & amp;0xFF);
IIC_Wait_Ack();
IIC_Send_Byte(data);
IIC_Wait_Ack();
  IIC_Stop();
if(device_addr==0xA0)
delay_ms(10);
else
delay_us(2);
}
 
uint16_t IIC_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead)
{<!-- -->
uint16_t data;
IIC_Start();
if(device_addr==0xA0)
IIC_Send_Byte(0xA0 + ((addr/256)<<1));
else
IIC_Send_Byte(device_addr);
IIC_Wait_Ack();
IIC_Send_Byte(addr & amp;0xFF);
IIC_Wait_Ack();
 
IIC_Start();
IIC_Send_Byte(device_addr + 1);
IIC_Wait_Ack();
if(ByteNumToRead == 1)
{<!-- -->
data=IIC_Read_Byte(0);
}
else
{<!-- -->
data=IIC_Read_Byte(1);
data=(data<<8) + IIC_Read_Byte(0);
}
IIC_Stop();
return data;
}



void read_AHT20_once(void)
{<!-- -->
delay_ms(10);

reset_AHT20();
delay_ms(10);

init_AHT20();
delay_ms(10);

startMeasure_AHT20();
delay_ms(80);

read_AHT20();
delay_ms(5);
}


void reset_AHT20(void)
{<!-- -->

I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("1");
else printf("1-n-");
I2C_WriteByte(0xBA);
ack_status = Receive_ACK();
if(ack_status) printf("2");
else printf("2-n-");
I2C_Stop();

/*
AHT20_OutData[0] = 0;
AHT20_OutData[1] = 0;
AHT20_OutData[2] = 0;
AHT20_OutData[3] = 0;
*/
}



void init_AHT20(void)
{<!-- -->
I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("3");
else printf("3-n-");
I2C_WriteByte(0xE1);
ack_status = Receive_ACK();
if(ack_status) printf("4");
else printf("4-n-");
I2C_WriteByte(0x08);
ack_status = Receive_ACK();
if(ack_status) printf("5");
else printf("5-n-");
I2C_WriteByte(0x00);
ack_status = Receive_ACK();
if(ack_status) printf("6");
else printf("6-n-");
I2C_Stop();
}



void startMeasure_AHT20(void)
{<!-- -->
//----------------
I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("7");
else printf("7-n-");
I2C_WriteByte(0xAC);
ack_status = Receive_ACK();
if(ack_status) printf("8");
else printf("8-n-");
I2C_WriteByte(0x33);
ack_status = Receive_ACK();
if(ack_status) printf("9");
else printf("9-n-");
I2C_WriteByte(0x00);
ack_status = Receive_ACK();
if(ack_status) printf("10");
else printf("10-n-");
I2C_Stop();
}



void read_AHT20(void)
{<!-- -->
uint8_t i;

for(i=0; i<6; i + + )
{<!-- -->
readByte[i]=0;
}

//-------------
I2C_Start();

I2C_WriteByte(0x71);
ack_status = Receive_ACK();
readByte[0]= I2C_ReadByte();
Send_ACK();

readByte[1]= I2C_ReadByte();
Send_ACK();

readByte[2]= I2C_ReadByte();
Send_ACK();

readByte[3]= I2C_ReadByte();
Send_ACK();

readByte[4]= I2C_ReadByte();
Send_ACK();

readByte[5]= I2C_ReadByte();
SendNot_Ack();
//Send_ACK();

I2C_Stop();

//-------------
if( (readByte[0] & amp; 0x68) == 0x08 )
{<!-- -->
H1 = readByte[1];
H1 = (H1<<8) | readByte[2];
H1 = (H1<<8) | readByte[3];
H1 = H1>>4;

H1 = (H1*1000)/1024/1024;

T1 = readByte[3];
T1 = T1 & 0x0000000F;
T1 = (T1<<8) | readByte[4];
T1 = (T1<<8) | readByte[5];

T1 = (T1*2000)/1024/1024 - 500;

AHT20_OutData[0] = (H1>>8) & amp; 0x000000FF;
AHT20_OutData[1] = H1 & 0x000000FF;

AHT20_OutData[2] = (T1>>8) & amp; 0x000000FF;
AHT20_OutData[3] = T1 & 0x000000FF;
}
else
{<!-- -->
AHT20_OutData[0] = 0xFF;
AHT20_OutData[1] = 0xFF;

AHT20_OutData[2] = 0xFF;
AHT20_OutData[3] = 0xFF;
printf("꧰üá?");

}
printf("\r\
");
printf("Temperature:%d%d.%d",T1/100,(T1/10),T1);
printf("Humidity:%d%d.%d",H1/100,(H1/10),H1);
printf("\r\
");
}




uint8_tReceive_ACK(void)
{<!-- -->
uint8_t result=0;
uint8_t cnt=0;

IIC_SCL = 0;
SDA_IN();
delay_us(4);

IIC_SCL = 1;
delay_us(4);

while(READ_SDA & amp; & amp; (cnt<100))
{<!-- -->
cnt + + ;
}

IIC_SCL = 0;
delay_us(4);

if(cnt<100)
{<!-- -->
result=1;
}
return result;
}



void Send_ACK(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 0;
delay_us(4);

IIC_SDA = 0;
delay_us(4);

IIC_SCL = 1;
delay_us(4);
IIC_SCL = 0;
delay_us(4);

SDA_IN();
}



void SendNot_Ack(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 0;
delay_us(4);

IIC_SDA = 1;
delay_us(4);

IIC_SCL = 1;
delay_us(4);

IIC_SCL = 0;
delay_us(4);

IIC_SDA = 0;
delay_us(4);
}


void I2C_WriteByte(uint8_t input)
{<!-- -->
uint8_t i;
SDA_OUT();
for(i=0; i<8; i + + )
{<!-- -->
IIC_SCL = 0;
delay_ms(5);

if(input & 0x80)
{<!-- -->
IIC_SDA = 1;
//delaymm(10);
}
else
{<!-- -->
IIC_SDA = 0;
//delaymm(10);
}

IIC_SCL = 1;
delay_ms(5);

input = (input<<1);
}

IIC_SCL = 0;
delay_us(4);

SDA_IN();
delay_us(4);
}


uint8_t I2C_ReadByte(void)
{<!-- -->
uint8_t resultByte=0;
uint8_t i=0, a=0;

IIC_SCL = 0;
SDA_IN();
delay_ms(4);

for(i=0; i<8; i + + )
{<!-- -->
IIC_SCL = 1;
delay_ms(3);

a=0;
if(READ_SDA)
{<!-- -->
a=1;
}
else
{<!-- -->
a=0;
}

//resultByte = resultByte | a;
resultByte = (resultByte << 1) | a;

IIC_SCL = 0;
delay_ms(3);
}

SDA_IN();
delay_ms(10);

return resultByte;
}


void set_AHT20sendOutData(void)
{<!-- -->
/*--------------------------
* 0xFA 0x06 0x0A temperature(2 Bytes) humility(2Bytes) short Address(2 Bytes)
* And Check (1 byte)
*-------------------------*/
AHT20sendOutData[3] = AHT20_OutData[0];
AHT20sendOutData[4] = AHT20_OutData[1];
AHT20sendOutData[5] = AHT20_OutData[2];
AHT20sendOutData[6] = AHT20_OutData[3];

// AHT20sendOutData[7] = (drf1609.shortAddress >> 8) & amp; 0x00FF;
// AHT20sendOutData[8] = drf1609.shortAddress & amp; 0x00FF;

// AHT20sendOutData[9] = getXY(AHT20sendOutData,10);
}


void I2C_Start(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 1;
delay_ms(4);

IIC_SDA = 1;
delay_ms(4);
IIC_SDA = 0;
delay_ms(4);

IIC_SCL = 0;
delay_ms(4);
}



void I2C_Stop(void)
{<!-- -->
SDA_OUT();
IIC_SDA = 0;
delay_ms(4);

IIC_SCL = 1;
delay_ms(4);

IIC_SDA = 1;
delay_ms(4);
}

Nextbsp_i2c.h

#ifndef __BSP_I2C_H
#define __BSP_I2C_H

#include "sys.h"
#include "delay.h"
#include "usart.h"
//PB6,PB7
 
#define SDA_IN() {<!-- -->GPIOB->CRL & amp;=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {<!-- -->GPIOB->CRL & amp;=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
 
//IO2ù×÷oˉêy
#define IIC_SCL PBout(6) //SCL
#define IIC_SDA PBout(7) //SDA
#define READ_SDA PBin(7)


//IIC?ùóD2ù×÷oˉêy
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(u8 txd);
u8 IIC_Read_Byte(unsigned char ack);
u8 IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
 
void IIC_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr);
uint16_t IIC_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead);


void read_AHT20_once(void);
void reset_AHT20(void);
void init_AHT20(void);
void startMeasure_AHT20(void);
void read_AHT20(void);
uint8_t Receive_ACK(void);
void Send_ACK(void);
void SendNot_Ack(void);
void I2C_WriteByte(uint8_t input);
uint8_t I2C_ReadByte(void);
void set_AHT20sendOutData(void);
void I2C_Start(void);
void I2C_Stop(void);
#endif


Nextsys.c

#include "sys.h"



void NVIC_Configuration(void)
{<!-- -->

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //éèNVIC?D·?×é2:2?àóè£?2?ìó|óè

}


Nextsys.h

#include "sys.h"



void NVIC_Configuration(void)
{<!-- -->

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

}

Fill in various environment configurations such as usart I2C sys system configuration based on the firmware library

Here is the information inside aht20

void read_AHT20_once(void)
{<!-- -->
delay_ms(10);

reset_AHT20(); //reset is to reset
delay_ms(10);

init_AHT20(); //iint initialize aht
delay_ms(10);

startMeasure_AHT20(); //Obviously, this is the start of measurement
delay_ms(80);

read_AHT20(); //This is a way to read sensor data
delay_ms(5);
}

The following is the data implementation of serial communication

First use flymcu to burn into the chip.
Then use sccom to continue serial communication.

The one above is the initial room temperature and humidity
The one below is the temperature and humidity after taking a breath of aht20, and you can clearly see the changes.

References: https://blog.csdn.net/qq_43279579/article/details/111597278