1, I2C bus protocol
1.1 what is the I2C protocol
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.
1.2 physical layer and protocol layer of I2C protocol
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).
Protocol layer:
It mainly defines the start and stop signals of communication, data validity, response, arbitration, clock synchronization and address broadcasting.
1.3 software I2C and hardware I2C
Software I2C:
Directly use the CPU core to control the high and low level 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.
Hardware I2C:
Direct use of 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.
difference:
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, Realization of AHT20 acquisition program
Learn about AHT20 chip
For specific information, please download the corresponding product introduction document. The data link is as follows
http://www.aosong.com/class-36.html
Specific code addition process
In the sample code provided by wildfire, open an empty project that contains only the firmware library. Add relevant codes to the project. Please refer to the following link for details of adding Codes:
https://blog.csdn.net/hhhhhh277523/article/details/111397514
Main code analysis:
void read_AHT20_once(void) { delay_ms(10); reset_AHT20();//Reset AHT20 chip delay_ms(10); init_AHT20();//Initialize AHT20 chip delay_ms(10); startMeasure_AHT20();//Start testing AHT20 chip delay_ms(80); read_AHT20();//Read the data collected by AHT20 delay_ms(5); }
2.AHT20 chip reads data
void read_AHT20(void) { uint8_t i; for(i=0; i<6; i++) { readByte[i]=0; } I2C_Start();//I2C start I2C_WriteByte(0x71);//I2C write data ack_status = Receive_ACK();//Received response information readByte[0]= I2C_ReadByte();//I2C read data Send_ACK();//Send response information 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();//I2C stop function //Judge whether the first byte read is 0x08, which is specified in the chip reading process. If there is no problem in the reading process, process the read data accordingly if( (readByte[0] & 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) & 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("Read failed!!!"); } printf("\r\n"); //According to the calculation formula of temperature and humidity in AHT20 chip, the final result is obtained and displayed through serial port printf("temperature:%d%d.%d",T1/100,(T1/10)%10,T1%10); printf("humidity:%d%d.%d",H1/100,(H1/10)%10,H1%10); printf("\r\n"); }
Line connection method:
The connection method of temperature and humidity sensor is realized by the software I2C used in this program, and the GPIO pins are PB6 and PB7. The specific definition codes are as follows:
#define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
#define IIC_SCL PBout(6) //SCL
#define IIC_SDA PBout(7) //SDA
#define READ_SDA PBin(7) therefore, SCL is connected to PB6 and SDA is connected to PB7. If the hardware I2C is used for implementation, you can view the schematic diagram of STM32, and you can see the hardware I2C interface. The I2C interfaces of wildfire stm32mini development board are PA2 and PA3. To realize the hardware I2C reading data, configure according to the above method to complete the communication
Operation results:
3, Temperature and humidity acquisition - OLED display
3.1 add OLED display code
Download link: https://github.com/Sunlight-Dazzling/stm32_AHT20_OLED/tree/main/User/usart
3.2 add function code
bsp_ Add in 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 t1,t2,t3,t4; uint8_t h1,h2,h3; uint8_t AHT20_OutData[4]; uint8_t AHT20sendOutData[10] = {0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}; char strTemp[30]; //Declare character array strTemp, initialize element 30 char strHumi[30]; //Declare character array strHumi, initialize element 30 int t; int h; float a; float b;
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] & 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) & 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("lyy"); } /*Display the collected temperature and humidity through the serial port printf("\r\n"); printf("Temperature:% d%d.%d",T1/100,(T1/10)%10,T1%10); printf("Humidity:% d%d.%d",H1/100,(H1/10)%10,H1%10); printf("\r\n");*/ t=T1/10; t1=T1%10; a=(float)(t+t1*0.1); h=H1/10; h1=H1%10; b=(float)(h+h1*0.1); sprintf(strTemp,"%.1f",a); //Call the Sprintf function to format the temperature data of DHT11 into the string array variable strTemp sprintf(strHumi,"%.1f",b); //Call the Sprintf function to format the humidity data of DHT11 into the string array variable strHumi GUI_ShowCHinese(16,00,16,"Temperature and humidity display",1); GUI_ShowCHinese(16,20,16,"temperature",1); GUI_ShowString(53,20,strTemp,16,1); GUI_ShowCHinese(16,38,16,"humidity",1); GUI_ShowString(53,38,strHumi,16,1); delay_ms(1500); delay_ms(1500); }
Add corresponding dot matrix font library:
"temperature",0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8, 0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00,/*"Temperature ", 0*/ "degree",0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20, 0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E,/*"Degrees ", 0*/ "wet",0x00,0x00,0x27,0xF8,0x14,0x08,0x14,0x08,0x87,0xF8,0x44,0x08,0x44,0x08,0x17,0xF8, 0x11,0x20,0x21,0x20,0xE9,0x24,0x25,0x28,0x23,0x30,0x21,0x20,0x2F,0xFE,0x00,0x00,/*"Wet ", 0*/ "display",0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0, 0x04,0x40,0x44,0x44,0x24,0x44,0x14,0x48,0x14,0x50,0x04,0x40,0xFF,0xFE,0x00,0x00,/*"Display ", 0*/ "show",0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x01,0x00, 0x01,0x00,0x11,0x10,0x11,0x08,0x21,0x04,0x41,0x02,0x81,0x02,0x05,0x00,0x02,0x00,/*"Display ", 0*/
main function:
int main(void) { delay_init(); //Delay function initialization uart_init(115200); IIC_Init(); NVIC_Configuration(); //Set NVIC interrupt packet 2: 2-bit preemption priority and 2-bit response priority OLED_Init(); //Initialize OLED OLED_Clear(0); while(1) { //printf("temperature and humidity display"); read_AHT20_once(); OLED_Clear(0); delay_ms(1500); } }
3.3 result display
4, References
Temperature and humidity acquisition based on STM32 -- OLED display
stm32 realizes the acquisition of temperature and humidity (AHT20) through I2C interface