AHT10,新一代温湿度传感器在尺寸与智能方面建立了新的标准:它嵌入了适于回流焊的双列扁平无引脚SMD 封装,底面 4 x 5mm ,高度1.6mm。传感器输出经过标定的数字信号,标准 I 2 C 格式。AHT10 配有一个全新设计的 ASIC专用芯片、一个经过改进的MEMS半导体电容式湿度传感元件和一个标准的片上温度传感元件,其性能已经大大提升甚至超出了前一代传感器的可靠性水平,新一代温湿度传感器,经过改进使其在恶劣环境下的性能更稳定。每一个传感器都经过校准和测试,在产品表面印有产品批号。由于对传感器做了改良和微型化改进,因此它的性价比更高,并且最终所有设备都将得益于尖端的节能运行模式。
应用范围主要在暖通空调 、除湿器、测试及检测设备、消费品、汽车 、自动控制、数据记录器、气象站、家电、湿度调节、医疗及其他相关温湿度检测控制。
一、模块来源
二、规格参数
工作电压:1.8~3.6V
工作电流:0.25~23uA
湿度误差:±2%RH
温度误差:±0.3℃
输出方式: IIC
管脚数量:3 Pin
以上信息见厂家资料文件
三、移植过程
我们的目标是将例程移植至CW32F030C8T6开发板上【能够测量环境温湿度】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
1、查看资料
器件地址为 0x38 ,但是最后一位是读写位,需要空出一位给读写位,因此需要左移一位,即 0x38<<1 得到 0X70
采集步骤:(写=0,读=1)
起始信号->器件地址左移1位+写 -> 等待传感器应答 -> 发送触发测量命令(0XAC)-> 等待传感器应答 -> 发送数据位0X33 -> 等待传感器应答 -> 发送数据位0x00 -> 等待传感器应答 -> 停止信号(可不加)-> 起始信号 ->器件地址左移1位+读 -> 等待传感器应答 -> 读取8位数据(状态字)-> 主机发送应答 -> 读取湿度高位数据 -> 主机发送应答 -> 读取湿度低位数据 -> 主机发送应答-> 读取湿度最后4位数据和温度最高的4位数据 -> -> 主机发送应答 -> 读取温度8数据 -> 主机发送应答-> 读取温度8位数据 -> 主机发送应答 -> 停止信号。
8位状态字,各个位表示的意义。
示例:
状态位 = 0x1C
0X1C = 0001 1100
bit7 = 设备空闲
bit6~5= NOR mode
bit4 = 保留
BIT3 = 1已校准
bit0~2= 保留
2
3
4
5
6
7
8
湿度换算公式:其中SRH等于读取到的20位湿度数据整合后的数据。
温度换算公式:其中ST等于读取到的20位温度数据整合后的数据。
2、引脚选择
3、移植至工程
模块工程参考入门手册工程模板
移植步骤中的导入.c和.h文件与第二章的第1小节【DHT11温湿度传感器】相同,只是将.c和.h文件更改为bsp_aht10.c与bsp_aht10.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件bsp_aht10.c中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-04-01 LCKFB-LP first version
*/
#include "bsp_aht10.h"
#include "stdio.h"
#include "board.h"
float Temperature = 0;
float Humidity = 0;
/******************************************************************
* 函 数 名 称:IIC_Start
* 函 数 说 明:IIC起始时序
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Start(void)
{
SDA_OUT();
SDA(1);
SCL(1);
delay_us(4);
SDA(0);
delay_us(4);
SCL(0);
}
/******************************************************************
* 函 数 名 称:IIC_Stop
* 函 数 说 明:IIC停止信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(4);
SCL(1);
SDA(1);
delay_us(4);
}
/******************************************************************
* 函 数 名 称:IIC_Send_Ack
* 函 数 说 明:主机发送应答或者非应答信号
* 函 数 形 参:0发送应答 1发送非应答
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Send_Ack(unsigned char ack)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(2);
if(!ack) SDA(0);
else SDA(1);
SCL(1);
delay_us(2);
SCL(0);
SDA(1);
}
/******************************************************************
* 函 数 名 称:I2C_WaitAck
* 函 数 说 明:等待从机应答
* 函 数 形 参:无
* 函 数 返 回:0有应答 1超时无应答
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned char I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 10;
SDA(1);
delay_us(1);
SCL(1);
delay_us(1);
SDA_IN();
delay_us(2);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(3);
}
if( ack_flag <= 0 )
{
IIC_Stop();
return 1;
}
else
{
SCL(0);
SDA_OUT();
}
SDA(0);
return ack;
}
/******************************************************************
* 函 数 名 称:Send_Byte
* 函 数 说 明:写入一个字节
* 函 数 形 参:dat要写人的数据
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void Send_Byte(uint8_t dat)
{
int i = 0;
SDA_OUT();
SCL(0);//拉低时钟开始数据传输
for( i = 0; i < 8; i++ )
{
SDA( (dat & 0x80) >> 7 );
delay_us(1);
SCL(1);
delay_us(2);
SCL(0);
delay_us(2);
dat<<=1;
}
}
/******************************************************************
* 函 数 名 称:Read_Byte
* 函 数 说 明:IIC读时序
* 函 数 形 参:无
* 函 数 返 回:读到的数据
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned char Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
SCL(0);
delay_us(2);
SCL(1);
delay_us(2);
receive<<=1;
if( SDA_GET() )
{
receive|=1;
}
delay_us(1);
}
SCL(0);
return receive;
}
/******************************************************************
* 函 数 名 称:AHT10Reset
* 函 数 说 明:软件复位
* 函 数 形 参:
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AHT10Reset(void)
{
IIC_Start();
Send_Byte(0x70);
I2C_WaitAck();
Send_Byte(0xba);
I2C_WaitAck();
IIC_Stop();
}
/******************************************************************
* 函 数 名 称:AHT10_GPIO_Init
* 函 数 说 明:AHT10的引脚初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AHT10_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化结构体
RCC_AHT10_ENABLE(); // 使能GPIO时钟
GPIO_InitStruct.Pins = GPIO_SDA|GPIO_SCL; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 输出速度高
GPIO_Init(PORT_AHT10, &GPIO_InitStruct); // 初始化
delay_ms(50);//延时50ms让传感器稳定
IIC_Start();
Send_Byte(0x70); //获取状态
//初始化校准
Send_Byte(0xe1);
Send_Byte(0x08);
Send_Byte(0x00);
IIC_Stop();
delay_ms(50);//延时50ms让传感器稳定
}
/**********************************************************
* 函 数 名 称:AHT10_Read
* 函 数 功 能:读取AHT10的温湿度数据
* 传 入 参 数:无
* 函 数 返 回:0读取成功
* 作 者:LC
* 备 注:无
**********************************************************/
unsigned char AHT10_Read(void)
{
char timeout = 0;
unsigned char buff[6] = {0};
unsigned int dat = 0;
IIC_Start();//起始信号
Send_Byte(0X38<<1 | 0); //器件地址+写命令
I2C_WaitAck(); //等待传感器应答
Send_Byte(0XAC);//寄存器地址:触发测量命令
I2C_WaitAck();//等待传感器应答
Send_Byte(0X33);//发送数据位
I2C_WaitAck();//等待传感器应答
Send_Byte(0X00);//发送数据位
I2C_WaitAck();//等待传感器应答
IIC_Stop(); //停止信号
do{
delay_ms(1);//超时判断,等待传感器采集数据
timeout++;
IIC_Start();//重新发送起始信号
Send_Byte(0X38<<1 | 1);//器件地址+写命令
}while( I2C_WaitAck() == 1 && timeout < 5 );
buff[0] = Read_Byte();//读取状态字
IIC_Send_Ack(0);//主机发送应答
buff[1] = Read_Byte();//湿度高8位数据
IIC_Send_Ack(0);//主机发送应答
buff[2] = Read_Byte();//湿度低8位数据
IIC_Send_Ack(0);//主机发送应答
buff[3] = Read_Byte();
IIC_Send_Ack(0);//主机发送应答
buff[4] = Read_Byte();
IIC_Send_Ack(0);//主机发送应答
buff[5] = Read_Byte();
IIC_Send_Ack(1);//主机发送应答
IIC_Stop();//停止信号
delay_ms(20);
//高位在前
dat = (((buff[1]<<12) | (buff[2]<<4)) | (buff[3]>>4));
Humidity = dat / 1048576.0 * 100.0;
dat = 0;
dat = ((buff[3] &0x0F) << 16 ) | ( buff[4] << 8) | buff[5];
Temperature = (dat/1048576.0) * 200 - 50;
AHT10Reset(); // AHT10复位
AHT10_GPIO_Init(); // GPIO重新初始化
return 0;
}
/**********************************************************
* 函 数 名 称:Get_Temperature
* 函 数 功 能:获取采集后的温度数据
* 传 入 参 数:无
* 函 数 返 回:温度数据,单位℃
* 作 者:LC
* 备 注:必须先采集与数据,否则返回0或者之前的数据
**********************************************************/
float Get_Temperature(void)
{
return Temperature;
}
/**********************************************************
* 函 数 名 称:Get_Humidity
* 函 数 功 能:获取采集后的湿度数据
* 传 入 参 数:无
* 函 数 返 回:湿度数据,单位%RH
* 作 者:LC
* 备 注:必须先采集与数据,否则返回0或者之前的数据
**********************************************************/
float Get_Humidity(void)
{
return Humidity;
}
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
在文件bsp_aht10.h中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#ifndef _BSP_AHT10_H_
#define _BSP_AHT10_H_
#include "board.h"
//端口移植
#define RCC_AHT10_ENABLE() __RCC_GPIOB_CLK_ENABLE()
#define PORT_AHT10 CW_GPIOB
#define GPIO_SDA GPIO_PIN_9
#define GPIO_SCL GPIO_PIN_8
//设置SDA输出模式
#define SDA_OUT() { \
GPIO_InitTypeDef GPIO_InitStruct; \
GPIO_InitStruct.Pins = GPIO_SDA; \
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; \
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; \
GPIO_Init(PORT_AHT10, &GPIO_InitStruct); \
}
//设置SDA输入模式
#define SDA_IN() { \
GPIO_InitTypeDef GPIO_InitStruct; \
GPIO_InitStruct.Pins = GPIO_SDA; \
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; \
GPIO_Init(PORT_AHT10, &GPIO_InitStruct); \
}
//获取SDA引脚的电平变化
#define SDA_GET() GPIO_ReadPin(PORT_AHT10, GPIO_SDA)
//SDA与SCL输出
#define SDA(x) GPIO_WritePin(PORT_AHT10, GPIO_SDA, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )
#define SCL(x) GPIO_WritePin(PORT_AHT10, GPIO_SCL, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )
void AHT10_GPIO_Init(void);
unsigned char AHT10_Read(void);
float Get_Temperature(void);
float Get_Humidity(void);
#endif
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
四、移植验证
在自己工程中的main主函数中,编写如下。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_aht10.h"
int32_t main(void)
{
board_init(); // 开发板初始化
uart1_init(115200); // 串口1波特率115200
AHT10_GPIO_Init();//AHT10引脚初始化
printf("Start\r\n");
while(1)
{
//采集温湿度
AHT10_Read();
//串口打印温度数据
printf("温度 = %.2f\r\n", Get_Temperature() );
//串口打印湿度数据
printf("湿度 = %.2f\r\n", Get_Humidity() );
printf("\n");
delay_ms(1000);
}
}
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
上电现象:每隔大约一秒测量一次温湿度。
模块移植成功案例代码:
链接:https://pan.baidu.com/s/13dMHBLOyabVYgR11D20U2Q?pwd=LCKF 提取码:LCKF