STM32基于IIC的温湿度采集(AHT20)


前言

本篇文章讲解了IIC协议的应用,区分了软件IIC和硬件IIC的区别,以及AHT20 向STM32 使用IIC 协议传输数据,并在上位机上面显示出来。
  • 使用芯片:STM32F103ZET6(正点原子)、AHT20(奥松)

  • 实验环境:KEIL5


IIC简介

IIC(Inter Integrated Circuit) 总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。它是由数据线 SDA和时钟SCL 构成的串行总线,可发送和接收数据。在CPU与被控 IC 之间、IC与IC之间进行双向传送, 高速 IIC 总线 一般可达 400kbps 以上 。
IIC总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。

开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

硬件IIC

硬件IIC对应芯片上的IIC外设,有相应IIC驱动电路,其所使用的IIC管脚也是专用的,就是配置寄存器,硬件产生IIC读写时序。

硬件IIC的效率要远高于软件的,而软件IIC由于不受管脚限制,接口比较灵活。

软件IIC

软件IIC一般是用GPIO管脚,用软件控制管脚状态以模拟IIC通信波形。

模拟IIC 是通过GPIO软件模拟寄存器的工作方式,而硬件(固件)IIC是直接调用内部寄存器进行配置。STM32的硬件IIC一直是令人诟病的地方,以至于很多情况下我们不得不选择使用模拟IIC的方式来在STM32上进行iic通讯。 软件模拟IIC简单方便,不必为繁琐的事件检测而费心。

AHT20简介

有关AHT20 的详细简介请查看博主之前的博客,这里只做简单介绍。

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

显示温湿度

编程实现

首先新建一个工程文件,在新建的工程文件目录下新建一个HARDWARE文件夹,在文件夹中添加IIC以及AHT20 文件夹。

其中IIC和LED的文件夹可以在其他例程文件中copy到该目录下,AHT20 文件可以在官网下载

下载位置:

在这里插入图片描述
添加文件夹:
在这里插入图片描述
(其中的LCD文件可以不添加)

然后在工程中添加新的分组,在分组中添加已经存在的文件。
在这里插入图片描述
(其中LCD和LED文件可以不添加,博主试过添加LED代码,添加进去,串口输出结果就不正确,目前还不太明白是什么原因。)

这里是博主已经完成好配置,并且编译成功后,所以在.c文件前面有+号。

接下来,在工程中找到AHT20.c文件(下载下来不是这个名称,就是里面的.c文件)里面有一个主函数,将主函数剪切出来,到工程中的主函数去。

以下是AHT20.c中的主函数

int32_t main(void)
{
 uint32_t CT_data[2];
	volatile int  c1,t1;
	SensorDelay_us(40000);//刚上电,延时40ms才可以读取状态
	
	if(!((AHT20_Read_Status()&0x08)==0x08))//首先发0x71读取状态字bit[3],如果=1,为校准输出,无须初始化!!!    正常情况下读回来的状态是0x1C或者是0x18,读回来是0x80表示忙状态;
	{
	AHT20_Init(); //初始化AHT20 
	}
	while(1)
	{
	 //DisableIrq(); //由于是模拟I2C,为读取数据更准确 ,读取之前禁止中断;
		
	 AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
    //AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 

	 c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值(放大了10倍)
	 t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)
	 }

 }	

然后根据调用的函数,更改里面的IIC的调用为新添加进去的IIC调用。(因为在AHT20中的函数,调用的IIC函数与STM32标准库中的IIC函数是不兼容的,所以需要一个一个的更改)类似以下方式的更改。

原AHT20.c

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

	SensorDelay_us(11038);//延时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();
	SensorDelay_us(11038);//延时10ms左右
}

改AHT20.c

void AHT20_Init(void)   //初始化AHT20
{	
	IIC_Init();
	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xa8);//0xA8进入NOR工作模式
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();

	SensorDelay_us(11038);//延时10ms左右

	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1
	IIC_Wait_Ack();
	IIC_Send_Byte(0x08);//相关寄存器bit[3]置1,为校准输出
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();
	SensorDelay_us(11038);//延时10ms左右
}

注意:是要根据自己的IIC 中的函数进行更改。

  • 将所用用到的函数更改即可
  • 其中延时函数可以保留(无影响)

主函数

#include "stm32f10x.h"
#include "AHT20.h"
#include "myiic.h"
#include "usart.h"
#include "delay.h"

int32_t main(void)
{
 uint32_t CT_data[2];
	volatile int  c1,t1;
	SensorDelay_us(40000);//刚上电,延时40ms才可以读取状态
	delay_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  uart_init(115200);	 //串口初始化为115200
	delay_ms(40);//刚上电,延时40ms才可以读取状态
	if(!((AHT20_Read_Status()&0x80)==0x80))//首先发0x71读取状态字bit[3],如果=1,为校准输出,无须初始化!!!    正常情况下读回来的状态是0x1C或者是0x18,读回来是0x80表示忙状态;
	{
	AHT20_Init(); //初始化AHT20 
	}
	while(1)
	{
	 AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
   c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值(放大了10倍)
	 t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)
		printf("湿度:%d  ",(c1/10));
		printf("温度:%d\n",(t1/10));
	 delay_ms(20000);
	 }
 }

硬件连接

硬件连接表:

AHT20STM32
VDD3.3V
GNDGND
SCLPB6
SDAPB7

硬件连接实物图:
在这里插入图片描述

实验结果

在这里插入图片描述
哈一口气,可以看到温度和湿度的变化。

本篇文章就讲到这里啦~

  • 3
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于Linux 4.9内核的AHT20 IIC驱动,用于采集温湿度的功能代码。在此之前,您需要先编写一个用户空间程序,用于打开IIC设备节点并读取温湿度数据。以下代码假设您已经完成了这一步骤,并定义了一个名为`aht20_read`的函数,用于读取AHT20温湿度数据。 ``` #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/kernel.h> // AHT20 I2C Address #define AHT20_I2C_ADDR 0x38 // AHT20 Commands #define AHT20_CMD_INIT 0b1110001 #define AHT20_CMD_MEASURE 0b10101100 #define AHT20_CMD_SOFT_RESET 0b10111010 static int aht20_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; u8 buf[3]; // Initialize AHT20 buf[0] = AHT20_CMD_INIT; ret = i2c_master_send(client, buf, 1); if (ret < 0) { dev_err(&client->dev, "Failed to send AHT20 initialization command\n"); return ret; } msleep(20); // Soft reset AHT20 buf[0] = AHT20_CMD_SOFT_RESET; ret = i2c_master_send(client, buf, 1); if (ret < 0) { dev_err(&client->dev, "Failed to send AHT20 soft reset command\n"); return ret; } msleep(20); return 0; } static int aht20_read_measurement(struct i2c_client *client, u16 *humidity, u16 *temperature) { int ret; u8 buf[6]; // Send measure command to AHT20 buf[0] = AHT20_CMD_MEASURE; ret = i2c_master_send(client, buf, 1); if (ret < 0) { dev_err(&client->dev, "Failed to send AHT20 measure command\n"); return ret; } msleep(80); // Read measurement data from AHT20 ret = i2c_master_recv(client, buf, sizeof(buf)); if (ret < 0) { dev_err(&client->dev, "Failed to read AHT20 measurement data\n"); return ret; } // Convert measurement data to humidity and temperature values *humidity = (buf[1] << 12) | (buf[2] << 4) | (buf[3] >> 4); *temperature = ((buf[3] & 0x0F) << 16) | (buf[4] << 8) | buf[5]; return 0; } static int aht20_read(struct i2c_client *client, u16 *humidity, u16 *temperature) { int ret; // Read measurement data from AHT20 ret = aht20_read_measurement(client, humidity, temperature); if (ret < 0) { dev_err(&client->dev, "Failed to read AHT20 measurement data\n"); return ret; } return 0; } static const struct i2c_device_id aht20_id[] = { { "aht20", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, aht20_id); static struct i2c_driver aht20_driver = { .driver = { .name = "aht20", }, .probe = aht20_probe, .id_table = aht20_id, }; module_i2c_driver(aht20_driver); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("AHT20 IIC Driver"); MODULE_LICENSE("GPL"); ``` 这段代码实现了从AHT20读取温湿度数据的功能。在用户空间程序中,您可以打开IIC设备节点并调用`aht20_read`函数来读取温湿度数据。例如: ``` int fd = open("/dev/i2c-1", O_RDWR); if (fd < 0) { perror("Failed to open IIC device node"); return -1; } int addr = 0x38; if (ioctl(fd, I2C_SLAVE, addr) < 0) { perror("Failed to set IIC slave address"); close(fd); return -1; } u16 humidity, temperature; if (read(fd, &humidity, sizeof(humidity)) != sizeof(humidity)) { perror("Failed to read humidity data"); close(fd); return -1; } if (read(fd, &temperature, sizeof(temperature)) != sizeof(temperature)) { perror("Failed to read temperature data"); close(fd); return -1; } printf("Humidity: %d%%\n", humidity); printf("Temperature: %d.%d C\n", temperature / 100, temperature % 100); close(fd); ``` 请注意,这只是一个示例代码,并且可能需要根据您的具体需求进行修改和调整。在实际使用中,请务必小心谨慎,以确保您的设备和数据的安全。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值