Data acquisition of AHT20 temperature and humidity sensor based on I2C protocol

This article will mainly introduce and explain what is "software I2C" and "hardware I2C"?

STM32F103 is used to complete the data acquisition of AHT20 temperature and humidity sensor based on I2C protocol, and the collected temperature humidity value is output through serial port

catalogue

1, I2C bus communication protocol

1.I2C protocol definition

2.I2C physical layer

3. Protocol layer

4. Hardware I2C and software I2C

2, Using AHT20 to complete temperature and humidity acquisition

1. Coding

2. Physical connection

3. Experimental results

3, Reference articles

1, I2C bus communication protocol

1.I2C protocol definition

  I2C communication protocol (Inter Integrated Circuit) is developed by Phiilps company. Due to its few pins, simple hardware implementation and strong scalability, it does not need external transceiver equipment of USART, CAN and other communication protocols. Now it is widely used in the communication between multiple integrated circuits (ICS) in the system.

2.I2C physical layer

I2C is a bus that supports devices. It can connect multiple I2C communication devices and support multiple communication hosts and multiple communication slaves. For I2C bus, only two bus lines are used, one bidirectional serial data line (SDA) and one serial clock line (SCL).

The common connection modes between I2C communication equipment are as follows:

I2C features are as follows:
► bus supporting multiple devices;

► the bus consists of SCL and SDA buses, one bidirectional serial data line (SDA) and one serial clock line (SCL). The data line is used to represent data, and the clock line is used for data transceiver synchronization;

► each device connected to the bus has a device address for selective communication between the host and multiple devices;

► the bus is connected to the power supply through the pull-up resistor. When the I2C device is idle, it will output the high resistance state. When all devices are idle and output the high resistance state, the pull-up resistor will pull the bus to the high level;

► when multiple hosts use the bus at the same time, the arbitration method is used to determine which device occupies the bus to prevent data transmission conflict;

► there are three transmission modes: the standard mode has a transmission rate of 100kbit/s, the fast mode is 400kbit/s, and the high-speed mode can reach 3.4Mbit/s, but most I2C devices do not support the high-speed mode at present;

► since the current consumed on the bus is very small, the number of devices expanded on the bus is mainly determined by the capacitive load, because the bus interface of each device has a certain equivalent capacitance. The capacitance in the line will affect the bus transmission speed. When the capacitance is too large, it may cause transmission errors. Therefore, its load capacity is 400pF, Therefore, the allowable length of the bus and the number of connected devices can be estimated;

3. Protocol layer

The protocol layer mainly defines the start and stop signals of communication, data validity, response, arbitration, clock synchronization and address broadcasting.

The I2C protocol layer mainly includes the following parts:
► start signal
► data transmission
► response signal
► stop signal

There are three types of signals in the process of I2C bus transmitting data: start signal, end signal and response signal.

When the start signal SCL is high level, SDA jumps from high level to low level and starts transmitting data.
When the end signal SCL is high level, SDA jumps from low level to high level and ends data transmission.
After receiving 8bit data, the IC receiving the response signal sends a specific low-level pulse to the IC transmitting the data, indicating that the data has been received. After sending a signal to the controlled unit, the CPU waits for the controlled unit to send a response signal. After receiving the response signal, the CPU determines whether to continue transmitting the signal according to the actual situation. If no response signal is received, it is judged that the controlled unit has failed.

Among these signals, the start signal is necessary, and the end signal and response signal can be omitted.

Start and stop signals of communication

 

4. Hardware I2C and software I2C

Hardware I2C: directly use the hardware I2C peripherals in STM32 chip.

Use of hardware I2C
As long as the corresponding registers are configured, the peripherals will generate the timing of standard serial port protocol. After initializing the I2C peripheral, you only need to set a register to position 1. At this time, the peripheral will control the corresponding SCL and SDA lines to automatically generate the I2C start signal, and the core does not need to directly control the level of the pin.

Software I2C: directly use the CPU core to control the high and low levels of GPIO output according to the requirements of I2C protocol, so as to simulate I2C.

Use of software I2C
When controlling the generation of I2C start signal, control the GPIO pin as SCL line to output high level, then control the GPIO pin as SDA line to complete the switching from high level to low level during this period, and finally control the SCL line to switch to low level, so as to output a standard I2C start signal.  

The difference between the two
Hardware I2C directly uses peripherals to control pins, which can reduce the burden of CPU. However, when using hardware I2C, some fixed pins must be used as SCL and SDA, while software analog I2C can use any GPIO pin, which is relatively flexible. The usage of hardware I2C is more complex, and the flow of software I2C is clearer. If you want to understand I2C protocol in detail, you may better understand this process by using software I2C. In the process of using I2C, hardware I2C communication may be faster and more stable.

2, Using AHT20 to complete temperature and humidity acquisition

1. Coding

I have pasted some important codes here to facilitate learning and research. The complete project documents are later

main.c

#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "bsp_i2c.h"


int main(void)
{	
	//Delay initialization
	delay_init();
	//Serial port initialization
	uart_init(115200);
	//
	IIC_Init();
	
	while(1)
	{
		read_AHT20_once();
		delay_ms(1500);
  }
}
/*********************************************END OF FILE**********************/

bsp_i2c.h

#ifndef __BSP_I2C_H
#define __BSP_I2C_H

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

 
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
//CRL = 0000 1111 1111 1111 1111 1111 1111 1111
//8<<28 = 1000 1111 1111 1111 1111 1111 1111 1111
//CRL = 1000 1111 1111 1111 1111 1111 1111 1111 = 0x8fffff indicates SDA input
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
//CRL = 0x3fff indicates SDA output


#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA	 
#define READ_ SDA pbin (7) / / SDA data reading 7 Pin


void IIC_Init(void);
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

 bsp_i2c.c

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

uint8_t   ack_status=0;
uint8_t   readByte[6];

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

uint8_t  AHT20_OutData[4];

/****************
 *Initialize I2C function
 ****************/
void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	//Enable high speed APB (APB2) peripheral clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );	
	
	//GPIO definition
	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, &GPIO_InitStructure);
	
	//Initialize SCL (Pin6) high level
	IIC_SCL=1;
	//Initialize SDA (Pin7) high level
	IIC_SDA=1;
}

/*********************
 *AHT20 Total function of data operation
 *********************/
void read_AHT20_once(void)
{
	printf("Read data");
	
	//Delay 10 minutes
	delay_ms(10);
	
  //Start sensor and soft reset before data transmission
	reset_AHT20();
	delay_ms(10);
  
	//View enable bit
	init_AHT20();
	delay_ms(10);
	
  //Trigger measurement
	startMeasure_AHT20();
	delay_ms(80);
  
	//Read data
	read_AHT20();
	delay_ms(5);
}


void reset_AHT20(void)
{
	//Data transmission start signal
	I2C_Start();
	
	//send data
	I2C_WriteByte(0x70);
	//Receive ACK signal
	ack_status = Receive_ACK();
	//Judge ACK signal
	if(ack_status)
	{
		printf(">");
	}
	else
		printf("×");
	
	//Send soft reset command (restart sensor system)
	I2C_WriteByte(0xBA);
	//Receive ACK signal
	ack_status = Receive_ACK();
	//Judge ACK signal
	if(ack_status)
		printf(">");
	else
		printf("×");
	
	//Stop I2C protocol
	I2C_Stop();
}

//0x70 - > 0111 0000 the first seven bits represent I2C address, and the eighth bit is 0, indicating write
//0xE1 - > check whether the calibration enable Bit[3] of the status word is 1
//0x08 0x00 - > two parameters of 0xbe command, see AHT20 reference manual for details
void init_AHT20(void)
{
	//Transmission start
	I2C_Start();

	//Write 0x70 data
	I2C_WriteByte(0x70);
	//Receive ACK signal
	ack_status = Receive_ACK();
	//Judge ACK signal
	if(ack_status)
		printf(">");
	else
		printf("×");
	
	//Write 0xE1 data
	I2C_WriteByte(0xE1);
	ack_status = Receive_ACK();
	if(ack_status)
		printf(">");
	else
		printf("×");
	
	//Write 0x08 data
	I2C_WriteByte(0x08);
	ack_status = Receive_ACK();
	if(ack_status)
		printf(">");
	else 
		printf("×");
	
	//Write 0x00 data
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) 
		printf(">");
	else 
		printf("×");
	
	//Stop I2C protocol
	I2C_Stop();
}

//0x70 - > 0111 0000 the first seven bits represent I2C address, and the eighth bit is 0, indicating write
//0xAC - > trigger measurement
//0x33 0x00 - > two parameters of 0xac command. See AHT20 reference manual for details
void startMeasure_AHT20(void)
{
	//Start I2C protocol
	I2C_Start();
	
	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status)
		printf(">");
	else 
		printf("×");
	
	I2C_WriteByte(0xAC);
	ack_status = Receive_ACK();
	if(ack_status) 
		printf(">");
	else 
		printf("×");
	
	I2C_WriteByte(0x33);
	ack_status = Receive_ACK();
	if(ack_status) 
		printf(">");
	else 
		printf("×");
	
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) 
		printf(">");
	else 
		printf("×");
	
	I2C_Stop();
}


void read_AHT20(void)
{
	uint8_t i;

	//Initialize readByte array
	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}

	I2C_Start();

	//One byte status word can be obtained by sending 0x71
	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	
	//Receive 6 8-bit data
	readByte[0]= I2C_ReadByte();
	//Send ACK signal
	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();
	//Send NACK signal
	SendNot_Ack();

	I2C_Stop();

	//Binary data processing of temperature and humidity
	//0x68 = 0110 1000
  //0x08 = 0000 1000	
	if( (readByte[0] & 0x68) == 0x08 )
	{
		H1 = readByte[1];
		//H1 shifts 8 bits left and phase with readByte[2], or 
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		//H1 shift right 4 bits
		H1 = H1>>4;

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

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

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

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

		AHT20_OutData[2] = (T1>>8) & 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("Done!\n");
	printf("----temperature:%d%d.%d °C\n",T1/100,(T1/10)%10,T1%10);
	printf("----humidity:%d%d.%d %%",H1/100,(H1/10)%10,H1%10);
	printf("\n\n");
}

//Receive ACK signal
uint8_t Receive_ACK(void)
{
	uint8_t result=0;
	uint8_t cnt=0;

	//Set SCL low level
	IIC_SCL = 0;
	//Set SDA to read data mode
	SDA_IN();
	delay_us(4);

	//Set SCL high level
	IIC_SCL = 1;
	delay_us(4);

	//Wait for the slave to send ACK signal, and the waiting time is 100 cycles
	while(READ_SDA && (cnt<100))
	{
		cnt++;
	}

	IIC_SCL = 0;
	delay_us(4);

	//If it is within the waiting time, the result is 1
	if(cnt<100)
	{
		result=1;
	}
	
	return result;
}

//Send ACK signal
void Send_ACK(void)
{
	//Set SDA to write data mode
	SDA_OUT();
	IIC_SCL = 0;
	delay_us(4);

	//Set SDA to low level
	IIC_SDA = 0;
	delay_us(4);

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

	SDA_IN();
}

//Send NACK signal
void SendNot_Ack(void)
{
	//Set SDA to write data mode
	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);
}

//Send a byte of data
void I2C_WriteByte(uint8_t  input)
{
	uint8_t  i;
	//Set SDA to write data mode
	SDA_OUT();
	
	//Circularly shift left to send 8-bit data
	for(i=0; i<8; i++)
	{
		IIC_SCL = 0;
		delay_ms(5);

		if(input & 0x80)
		{
			IIC_SDA = 1;
		}
		else
		{
			IIC_SDA = 0;
		}

		IIC_SCL = 1;
		delay_ms(5);

		input = (input<<1);
	}

	IIC_SCL = 0;
	delay_us(4);

	SDA_IN();
	delay_us(4);
}	

//Circularly detect the level state of SDA and store it
uint8_t I2C_ReadByte(void)
{
	uint8_t  resultByte=0;
	uint8_t  i=0, a=0;

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

	//Cycle detection
	for(i=0; i<8; i++)
	{
		IIC_SCL = 1;
		delay_ms(3);

		a=0;
		if(READ_SDA)
		{
			a=1;
		}
		else
		{
			a=0;
		}

		resultByte = (resultByte << 1) | a;

		IIC_SCL = 0;
		delay_ms(3);
	}

	SDA_IN();
	delay_ms(10);

	return   resultByte;
}

//Set I2C protocol start
void I2C_Start(void)
{
	SDA_OUT();
	
	IIC_SCL = 1;
	delay_ms(4);

	//The process of SDA jumping from 1 to 0
	//Indicates the start signal
	IIC_SDA = 1;
	delay_ms(4);
	IIC_SDA = 0;
	delay_ms(4);

	//SCL becomes 0
	//Indicates that SDA data is invalid, and SDA can perform level switching at this time
	IIC_SCL = 0;
	delay_ms(4);
}

//Set I2C protocol stop
void I2C_Stop(void)
{
	SDA_OUT();
	
	//SCL high level, SDA high level
	//Stop timing
	IIC_SDA = 0;
	delay_ms(4);
	IIC_SCL = 1;
	delay_ms(4);

	//SDA switches to high level
	IIC_SDA = 1;
	delay_ms(4);
}

  Complete engineering documents

Link: https://pan.baidu.com/s/16FMDU_bJAJWz237Ia3iXJg  
Extraction code: 1234  


2. Physical connection

Because my board is the ministm32 development board of punctual atom, there is no need to connect usb to serial port, and the temperature sensor can be connected.

VCC→3V3,GND→GND,SCL→PB6,SDA→PB7 

3. Experimental results

After compiling and burning the code into stm32 board, open the serial port assistant, cover the temperature sensor with your hand and observe the temperature and humidity changes:

 

3, Reference articles

https://blog.csdn.net/qq_35701387/article/details/119315176?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163739778516780271552514%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163739778516780271552514&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-119315176.first_rank_v2_pc_rank_v29&utm_term=I2C+%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AE%28Inter%EF%BC%8DIntegrated+Circuit%29%E6%98%AF%E7%94%B1+Phiilps+%E5%85%AC%E5%8F%B8%E5%BC%80%E5%8F%91%E7%9A%84%EF%BC%8C%E7%94%B1%E4%BA%8E%E5%AE%83%E5%BC%95%E8%84%9A%E5%B0%91%EF%BC%8C%E7%A1%AC%E4%BB%B6%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95%EF%BC%8C%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7%E5%BC%BA%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81+USART%E3%80%81CAN+%E7%AD%89%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AE%E7%9A%84%E5%A4%96%E9%83%A8%E6%94%B6%E5%8F%91%E8%AE%BE%E5%A4%87%EF%BC%8C%E7%8E%B0%E5%9C%A8%E8%A2%AB%E5%B9%BF%E6%B3%9B%E5%9C%B0%E4%BD%BF%E7%94%A8%E5%9C%A8%E7%B3%BB%E7%BB%9F%E5%86%85%E5%A4%9A%E4%B8%AA%E9%9B%86%E6%88%90%E7%94%B5%E8%B7%AF%28IC%29%E9%97%B4%E7%9A%84%E9%80%9A%E8%AE%AF%E3%80%82&spm=1018.2226.3001.4187

 https://blog.csdn.net/ssj925319/article/details/111461000?spm=1001.2014.3001.5502https://blog.csdn.net/ssj925319/article/details/111461000?spm=1001.2014.3001.5502

Tags: Single-Chip Microcomputer

Posted on Sat, 20 Nov 2021 17:41:28 -0500 by Flames