STM32Cube&Keil——STM32C8T6:基于IIC协议的温湿度采集(奥松AHT20温湿度传感器)

一、IIC通信协议

(一)IIC协议

IIC(Inter-Integrated Circuit)通信协议,也被称为I2C,是一种串行通信协议,广泛应用于各种电子设备之间的数据传输。IIC通信协议由飞利浦(Philips)公司在20世纪80年代开发.

(二)工作原理

IIC通信协议采用了两根信号线:时钟线(SCL)和数据线(SDA)。其中,时钟线由主设备控制,用于生成时钟信号,而数据线用于双向的数据传输。在IIC通信协议中,设备分为主设备(Master)和从设备(Slave)。主设备负责控制整个通信过程,而从设备则接受主设备的控制并根据需要提供数据。

(三)时序

IIC通信协议的时序分为开始信号、地址字节、数据字节和停止信号四个阶段。

  1. 开始信号(Start Signal):
    主设备通过拉低数据线(SDA)时钟线(SCL)仍为高电平来发送开始信号。此时,从设备需准备好接收数据,并等待地址字节的到来。

  2. 地址字节(Address Byte):
    主设备发送一个地址字节到从设备以确定通信对象。地址字节的高七位是设备的地址,最低一位是读写控制位,通常为0表示写操作,1表示读操作。此时,从设备会检查其地址是否与发送的地址字节匹配。

  3. 数据字节(Data Byte):
    主设备和从设备之间的数据传输是通过数据字节来完成的。主设备发送数据字节,从设备接收数据字节。数据的传输是以字节为单位的,每个数据字节传输后都会有一个应答信号。

  4. 停止信号(Stop Signal):
    主设备发送停止信号作为传输的结束标志。停止信号通过将数据线从低电平拉升至高电平实现,此时时钟线仍然保持高电平。

在这里插入图片描述

(四)总结

IIC通信协议是一种简单而有效的串行通信协议,广泛应用于各种电子设备之间的数据传输。它具有以下几个特点:

  1. 简单:IIC通信协议仅使用两根信号线,使得它在硬件电路实现上非常简单。

  2. 双向传输:数据线(SDA)用于主设备和从设备之间的双向数据传输,使得主设备可以向从设备发送控制指令,并接收从设备返回的数据。

  3. 多从设备:IIC支持多个从设备连接到同一条总线上,每个从设备都有独立的地址,主设备可以通过地址字节确定要与哪个从设备通信。

  4. 时钟同步:通过时钟线(SCL)的协调,主设备和从设备之间的数据传输是同步的,提高了通信的可靠性。

  5. 强应答机制:每传输完一个字节的数据,接收端都会发送一个应答信号,以确保发生错误时能及时得到通知。

二、程序

(一)新建项目、编写代码

1.STM32Cube——配置新项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.Keil——编写代码

官网代码下载:AHT20芯片代码

(1)新建AHT文件并在Keil中添加

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(2)编写程序
①AHT20-21_DEMO_V1_3.c

添加以下头文件,以及将原PB14、PB15修改为PB6与PB7

#include "gpio.h"
#include "i2c.h"   

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 SCL_Pin_Output_High(void) //SCL输出高电平,P6作为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);
	
}




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(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)) a=1;
		Byte = (Byte<<1)|a;
		
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
		Delay_5us();
	}
  SDA_Pin_IN_FLOATING();
	SensorDelay_us(8);	
	return Byte;
}
②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
③main.c

引入头文件以及

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

/* USER CODE BEGIN PTD */
int fputc(int ch,FILE *f)
{
    HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);    
		//等待发送结束	
		while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET){
		}		

    return ch;
}

  /* USER CODE BEGIN 2 */
  AHT20_Init();
  Delay_1ms(500);

  /* USER CODE END 2 */

  while (1)
  {
    /* USER CODE END WHILE */
		//AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
		AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
	

		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\n");
		HAL_Delay(1000);
		printf("温度:%d%d.%d",t1/100,(t1/10)%10,t1%10);
		printf("湿度:%d%d.%d",c1/100,(c1/10)%10,c1%10);
		printf("\r\n");
		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\n");
		HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

(二)运行结果

I2C

三、总结

通过使用I2C协议与AHT20传感器完成了此次温湿度采集,让我对传感器的使用更加了解,以及对I2C协议更加了解。

四、引用

【霁夜暖玉>】STM32基于IIC协议的温湿度(AHT20)采集
【嵌入式杂谈】【通信协议】IIC通信协议详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值