• 通过STM32Cube配置完成基于I2C协议的AHT20温湿度传感器的数据采集



    前言

    • 硬件:stm32f103c8t6 核心板
    • 软件:STM32CubeMX 6.4.0
    • 软件:keil5 mdk
    • 软件:野火串口调试助手

    一、I2C协议

    1、应用

    I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地
    使用在系统内多个集成电路(IC)间的通讯。

    2、组成

    最基本的是把它分为物理层和协议层
    物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。
    协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流

    - I2C 通讯设备之间的常用连接方式

    在这里插入图片描述
    - 物理层
    I2C是一个支持设备的总线。可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。对于I2C 总线,只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。
    - 协议层
    I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

    - STM32的I2C架构:
    在这里插入图片描述

    - 通讯的起止:
    在这里插入图片描述

    当 SCL 线是高电平时 SDA 线从高电平向低电平切换,这个情况表示通讯的起始。当 SCL 是高电平时 SDA 线由低电平向高电平切换,表示通讯的停止。起始和停止信号一般由主机产生。

    • 数据的有效性
      在这里插入图片描述

    SDA 数据线在 SCL的每个时钟周期传输一位数据。传输时,SCL为高电平的时候 SDA表示的数据有效,即此时的 SDA为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL为低电平时,SDA的数据无效,一般在这个时候 SDA进行电平切换,为下一次表示数据做好准备。

    • 响应
      在这里插入图片描述

    I2C 的数据和地址传输都带响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。作为数据接收端时,当设备(无论主从机)接收到 I2C 传输的一个字节数据或地址后,若希望对方继续发送数据需要向对方发送“应答(ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号,发送方接收到该信号后会产生一个停止信号,结束信号传输。

    3、软件I2C和硬件I2C

    3.1软件I2C

    通过CPU 控制每个时刻的引脚状态来控制 GPIO 引脚电平产生通讯时序的方式称为软件I2C。

    3.2硬件I2C

    STM32 的 I2C 片上外设专门负责实现 I2C 通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种通过外设进行数据收发的方式称为硬件I2C。
    - 差别

    硬件 I2C 直接使用外设来控制引脚,可以减轻 CPU 的负担。不过使用硬件I2C 时必须使用某些固定的引脚作为 SCL 和 SDA,软件模拟 I2C 则可以使用任意 GPIO 引脚,相对比较灵活。对于硬件I2C用法比较复杂,软件I2C的流程更清楚一些。如果要详细了解I2C的协议,使用软件I2C可能更好的理解这个过程。在使用I2C过程,硬件I2C可能通信更加快,更加稳定。

    二、通过硬件I2C协议采集AHT20的数据

    1、配置项目

    默认你已经创建了一个新项目

    • 时钟RCC配置,将HSE选为外部晶振模式

    在这里插入图片描述

    • SYS设置,选择Serial Wire模式。

    在这里插入图片描述

    • 设置USART
      在这里插入图片描述
    • 设置允许中断

    在这里插入图片描述

    • I2C设置
      在这里插入图片描述
    • 设置DMA模式
      在这里插入图片描述
      在这里插入图片描述
    • RCC时钟
      在这里插入图片描述

    设置工程路径、工程名,最后导出文件。使用keil打开并进行编写。

    2、配置代码

    • 新建一个文件夹,里面放置两个文件:

    AHT20-21_DEMO_V1_3.c和AHT20-21_DEMO_V1_3.h

    然后通过小方块创建一个工程文件夹,将刚刚的两个文件添加进来,后面需要进行修改.
    在这里插入图片描述

    • 导入文件路径

    复制前面新建的文件夹路径

    在这里插入图片描述

    设置文件路径

    在这里插入图片描述
    在这里插入图片描述
    将刚刚文件路径放在最后步骤2那里,然后一致点击ok返回。

    • 因为后面重写了prntf函数,需要勾选允许微库。
      在这里插入图片描述

    • 修改AHT20-21_DEMO_V1_3.h文件

    #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配置为输出 , 并设置为高电平, PB15作为I2C的SDA
    void SDA_Pin_Output_Low(void);  //将P15配置为输出  并设置为低电平
    void SDA_Pin_IN_FLOATING(void);  //SDA配置为浮空输入
    void SCL_Pin_Output_High(void); //SCL输出高电平,P14作为I2C的SCL
    void SCL_Pin_Output_Low(void); //SCL输出低电平
    void Init_I2C_Sensor_Port(void); //初始化I2C接口,输出为高电平
    void I2C_Start(void);		 //I2C主机发送START信号
    void AHT20_WR_Byte(uint8_t Byte); //往AHT20写一个字节
    uint8_t AHT20_RD_Byte(void);//从AHT20读取一个字节
    uint8_t Receive_ACK(void);   //看AHT20是否有回复ACK
    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); //向AHT20发送AC命令
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 修改AHT20-21_DEMO_V1_3.c文件
    /*******************************************/
    /*@版权所有:广州奥松电子有限公司          */
    /*@作者:温湿度传感器事业部                */
    /*@版本: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)//延时函数
    {
    		
    	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配置为输出 , 并设置为高电平, PB7作为I2C的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,& 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,& 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,&GPIO_InitStruct);
    }
    
    
    void SCL_Pin_Output_High(void) //SCL输出高电平,P14作为I2C的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,& GPIO_InitStruct);
    	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
    
    	
    	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
    	GPIO_InitStruct.Pin = GPIO_PIN_6;
    	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    	HAL_GPIO_Init(GPIOB,& GPIO_InitStruct);
    	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
    	
    }
    void I2C_Start(void)		 //I2C主机发送START信号
    {
    	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();
    		}	
    			
        SCL_Pin_Output_High();
    		Delay_4us();
    		Data <<= 1;
    		 
    	}
    	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();
    	
    	SDA_Pin_IN_FLOATING();
    	SensorDelay_us(8);	
    	
    	for(i=0;i<8;i++)
    	{
        SCL_Pin_Output_High();
    		
    		Delay_5us();
    		a=0;
    		
    		//if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)) a=1;
    		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)) a=1;
    		Byte = (Byte<<1)|a;
    		
    		//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)   //看AHT20是否有回复ACK
    {
    	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))  && 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 & 0x68)==0x08)
    		 return 1;
       else  return 0;
     }
    
    void AHT20_SendAC(void) //向AHT20发送AC命令
    {
    
    	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&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();//向AHT10发送AC命令
    	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传递数组
    	
    	AHT20_SendAC();//向AHT10发送AC命令
    	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();
    	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();
    	
    	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; //温度
    		
    	}
    	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);//0xA8进入NOR工作模式
    	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)
    {
    	
    	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();
    	
      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();
    	
    	Byte_second=0x00;
    	Byte_third =0x00;
    }
    
    void AHT20_Start_Init(void)
    {
    	JH_Reset_REG(0x1b);
    	JH_Reset_REG(0x1c);
    	JH_Reset_REG(0x1e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 将main.c文件里main函数包括上面的头文件等信息删除,换成下面代码
    #include "main.h"
    #include "dma.h"
    #include "i2c.h"
    #include "usart.h"
    #include "gpio.h"
    #include "AHT20-21_DEMO_V1_3.h" 
    #include 
    #include 
    int fputc(int ch,FILE *f)//重新printf
    {
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);    
    		while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET){
    		}		
        return ch;
    }
    void SystemClock_Config(void);
    volatile int  c1,t1;
    uint32_t CT_data[2]={0,0};
    int main(void)
    {
      HAL_Init();
      SystemClock_Config();
      MX_USART1_UART_Init();
      MX_DMA_Init();
      MX_I2C1_Init();	
    	AHT20_Init();//放在其它之后
      if((AHT20_Read_Status()&0x18)!=0x18)
    	{
    		AHT20_Start_Init(); //重新初始化寄存器
    		Delay_1ms(10);
    	}
    
    
      while (1)
      {
       
    		AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
        //AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
    	  c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1(放大了10倍)
    	  t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1(放大了10倍)	
    		printf("湿度:%d%s",c1/10,"%");
    	  printf("温度:%d%s",t1/10,"℃");
    	  printf("\r\n");
    		HAL_Delay(3000);
    
      }
     
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    编译烧录均无问题

    三、效果

    在这里插入图片描述

    20221116_233110


    四、总结

    学习了IIC协议,清楚协议大致流程。第一次使用传感器进行实验,感觉很酷。也是第一次调用厂商的代码,并且通过STM32Cube进行配置相当方便,这样应该是以后工作的常态吧(使用厂商的代码)。

    五、参考资料

    https://blog.csdn.net/qq_43279579/article/details/111597278
    https://blog.csdn.net/Mouer__/article/details/121514102

  • 相关阅读:
    Android 12/12L 全面升级、微信和“吃鸡”都在用 Flutter,2021 Google 开发者大会你看了吗?
    SPASS-参数估计与假设检验
    unity 限制 相机移动 区域(无需碰撞检测)
    RabbitMQ 消息应答与发布
    调优zuul1.x(基于arthas)
    Git日常使用技巧 - 笔记
    自动部署工具PM2
    java基于 springboot+vue的校园出入管理系统 element
    基于PHP+MySQL的在线投票系统设计与实现
    Glide的使用及源码分析
  • 原文地址:https://blog.csdn.net/qq_52215423/article/details/127887672