AGS10是一款采用数字信号输出的MEMS TVOC传感器。配置了专用的数字模块采集技术和气体感应传感技术,确保了产品具有极高的可靠性与卓越的长期稳定性,同时具有低功耗、高灵敏度、快速响应、成本低、驱动电路简单等特点。
一、模块来源
采购链接:
二、规格参数
工作电压 : 3.0-6.0 V
典型功率 : 75mW
采样周期 : ≥2s
接口速率 :I2C从机模式(≤15kHz)
预热时间 : ≥120s
工作温度 : 0~50℃
工作湿度 : 0~95%RH
寿命 : >5年(25℃,清洁空气中)
输出单位 : ppb
测量范围 : 0~99999 ppb
典型精度( 25℃/50%RH): 25% 读数
标准测试气体 : 乙醇
模块尺寸:15*10.6mm
以上信息见厂家资料文件
三、移植过程
1、查看资料
工作原理
AGS10传感器采用标准I 2C通信协议,适应多种设备。IIC的物理接口包含串行数据信号(SDA)与串行时钟信号(SCL)两个接口。两个接口需通过1kΩ~10kΩ电阻上拉至VDD。SDA用于读、写传感器数据。SCL上电必须保持高电平直到进行IIC通信开始,否则会引起I 2C通讯不良。当I 2C通信时SCL用于主机与传感器之间的通讯同步。多个I2C设备可以共享总线,但是只能允许一个主机设备出现在总线上。既然采用的是IIC,那么我们需要知道它的IIC通信地址。
读取TVOC数据的步骤:
2、引脚选择
VCC | 3V3 |
GND | GND |
SCL | PA2 |
SDA | PA3 |
3、代码编写
新建两个文件 bsp_ags10.c
和 bsp_ags10.h
,并且将头文件路径添加到编译器中。
在文件 bsp_ags10.c
和 bsp_ags10.h
中,编写如下代码。
c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 文档网站:wiki.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 嘉立创社区问答:https://www.jlc-bbs.com/lckfb
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#ifndef BSP_CODE_BSP_AGS10_H_
#define BSP_CODE_BSP_AGS10_H_
#include "gd32vw55x.h"
#include "systick.h"
#ifndef u8
#define u8 uint8_t
#endif
#ifndef u16
#define u16 uint16_t
#endif
#ifndef u32
#define u32 uint32_t
#endif
#ifndef delay_ms
#define delay_ms(x) delay_1ms(x)
#endif
#ifndef delay_us
#define delay_us(x) delay_1us(x)
#endif
#define Module_RCU_ENABLE() \
rcu_periph_clock_enable(Module_SCL_RCU); \
rcu_periph_clock_enable(Module_SDA_RCU);
#define Module_SCL_RCU RCU_GPIOA
#define Module_SCL_PORT GPIOA
#define Module_SCL_PIN GPIO_PIN_2 //SCL
#define Module_SDA_RCU RCU_GPIOA
#define Module_SDA_PORT GPIOA
#define Module_SDA_PIN GPIO_PIN_3 //SDA
//SDA输入模式
#define SDA_IN() \
gpio_mode_set(Module_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, Module_SDA_PIN);
//SDA输出模式
#define SDA_OUT() \
gpio_mode_set(Module_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Module_SDA_PIN); \
gpio_output_options_set(Module_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, Module_SDA_PIN);
#define SCL(BIT) gpio_bit_write(Module_SCL_PORT, Module_SCL_PIN, BIT)
#define SDA(BIT) gpio_bit_write(Module_SDA_PORT, Module_SDA_PIN, BIT)
#define SDA_GET() gpio_input_bit_get(Module_SDA_PORT, Module_SDA_PIN)
void ags10_init(void);
char ags10_read(uint32_t *tvoc_dat);
#endif /* BSP_CODE_BSP_AGS10_H_ */
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
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
c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 文档网站:wiki.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 嘉立创社区问答:https://www.jlc-bbs.com/lckfb
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#include "bsp_ags10.h"
//起始信号
void AGS10_IIC_Start(void)
{
SDA_OUT();
SDA(1);
SCL(1);
delay_1us(5);
SDA(0);
delay_1us(5);
SCL(0);
delay_1us(5);
}
//停止信号
void AGS10_IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_1us(5);
SDA(1);
delay_1us(5);
}
//发送非应答
void AGS10_IIC_Send_Nack(void)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
SDA(1);
SCL(1);
delay_1us(5);
SCL(0);
SDA(1);
}
//发送应答
void AGS10_IIC_Send_Ack(void)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
SDA(0);
SCL(1);
delay_1us(5);
SCL(0);
SDA(1);
}
/**********************************************************
* 函 数 名 称:I2C_WaitAck
* 函 数 功 能:等待从机应答
* 传 入 参 数:无
* 函 数 返 回:1=非应答 0=应答
* 作 者:LCKFB
* 备 注:无
**********************************************************/
unsigned char AGS10_I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 100;
SDA_IN();
SDA(1);
delay_us(5);
SCL(1);
delay_us(5);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_1us(5);
}
//非应答
if( ack_flag <= 0 )
{
AGS10_IIC_Stop();
return 1;
}
else//应答
{
SCL(0);
SDA_IN();
}
return ack;
}
//发送一个字节
void AGS10_IIC_Send_Byte(uint8_t dat)
{
int i = 0;
SDA_OUT();
SCL(0);
for( i = 0; i < 8; i++ )
{
SDA( (dat & 0x80) >> 7 );
delay_1us(5);
SCL(1);
delay_1us(5);
SCL(0);
delay_1us(5);
dat<<=1;
}
}
//接收一个字节
unsigned char AGS10_IIC_Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
SCL(0);
delay_1us(5);
SCL(1);
delay_1us(5);
receive<<=1;
if( SDA_GET() )
{
receive |= 1;
}
}
SCL(0);
return receive;
}
/**********************************************************
* 函 数 名 称:ags10_read
* 函 数 功 能:读取AGS10的TVOC浓度数据
* 传 入 参 数:无
* 函 数 返 回:0: 成功
* 1: 通信失败
* 2:发送失败
* 3:等待超时
* 4: 校验失败
* 作 者:LCKFB
* 备 注:
**********************************************************/
char ags10_read(uint32_t *tvoc_dat)
{
uint8_t timeout = 0;
uint8_t data[5] = {0};
AGS10_IIC_Start();
AGS10_IIC_Send_Byte(0X34);
if( AGS10_I2C_WaitAck() == 1 ) return 1;
AGS10_IIC_Send_Byte(0X00);
if( AGS10_I2C_WaitAck() == 1 ) return 2;
AGS10_IIC_Stop();
do{
delay_1ms(1);
timeout++;
AGS10_IIC_Start();
AGS10_IIC_Send_Byte(0X35);
}while( (AGS10_I2C_WaitAck() == 1) && (timeout < 50) );
//如果超时
if( timeout >= 50 ){
printf("\ntimeout\r\n");
return 3;
}
data[0] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[1] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[2] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[3] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[4] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Nack();
AGS10_IIC_Stop();
*tvoc_dat = ((uint32_t)data[1]<<16) | ((uint16_t)data[2]<<8) | data[3];
return 0;
}
/**********************************************************
* 函 数 名 称:ags10_init
* 函 数 功 能:ags10初始化
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LCKFB
* 备 注:
**********************************************************/
void ags10_init(void)
{
Module_RCU_ENABLE();
//SCL引脚初始化
gpio_mode_set(Module_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Module_SCL_PIN);
gpio_output_options_set(Module_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, Module_SCL_PIN);
//SDA引脚初始化
gpio_mode_set(Module_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Module_SDA_PIN);
gpio_output_options_set(Module_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, Module_SDA_PIN);
SCL(1);
SDA(1);
delay_ms(100); // 等待传感器稳定
}
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
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
四、移植验证
在 src\main.c
中输入代码如下:
c
#include "gd32vw55x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32vw553h_eval.h"
#include "bsp_ags10.h"
/*!
\brief toggle the led every 500ms
\param[in] none
\param[out] none
\retval none
*/
void led_spark(void)
{
static __IO uint32_t timingdelaylocal = 0U;
if(timingdelaylocal) {
if(timingdelaylocal < 500U) {
gd_eval_led_on(LED1);
} else {
gd_eval_led_off(LED1);
}
timingdelaylocal--;
} else {
timingdelaylocal = 1000U;
}
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
#ifdef __FIRMWARE_VERSION_DEFINE
uint32_t fw_ver = 0;
#endif /* __FIRMWARE_VERSION_DEFINE */
/* configure systick */
systick_config();
eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1);
/* initilize the LEDs, USART and key */
gd_eval_led_init(LED1);
gd_eval_com_init(EVAL_COM0);
gd_eval_key_init(KEY_TAMPER_WAKEUP, KEY_MODE_GPIO);
#ifdef __FIRMWARE_VERSION_DEFINE
fw_ver = gd32vw55x_firmware_version_get();
printf("\r\n= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =\r\n\n");
printf("\r\n=== Welcome to use the LC-GD32VW553-HMQ6 development board ====\r\n\n");
printf("\r\n======================= www.lckfb.com =========================\r\n\n");
printf("\r\n======================= wiki.lckfb.com ========================\r\n\n");
printf("\r\n= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =\r\n");
/* print firmware version */
printf("\r\nGD32VW55X series firmware version: V%d.%d.%d", (uint8_t)(fw_ver >> 24), (uint8_t)(fw_ver >> 16), (uint8_t)(fw_ver >> 8));
#endif /* __FIRMWARE_VERSION_DEFINE */
/* print out the clock frequency of system, AHB, APB1 and APB2 */
printf("\r\nCK_SYS is %d\r\n", rcu_clock_freq_get(CK_SYS));
printf("\r\nCK_AHB is %d\r\n", rcu_clock_freq_get(CK_AHB));
printf("\r\nCK_APB1 is %d\r\n", rcu_clock_freq_get(CK_APB1));
printf("\r\nCK_APB2 is %d\r\n", rcu_clock_freq_get(CK_APB2));
/* initialize the AGS10 sensor */
ags10_init();
printf("\r\nAGS10 sensor initialized.\r\n");
while(1)
{
/* read TVOC data from AGS10 sensor */
uint32_t tvoc_data = 0;
if (ags10_read(&tvoc_data) == 0) {
printf("\r\nTVOC Data: %lu ppb\r\n", tvoc_data);
} else {
printf("\r\nFailed to read TVOC data.\r\n");
}
/* delay for a while */
delay_1ms(500);
}
}
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
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
编译烧录。
【代码下载】
- 跳转到
下载中心
去下载模块移植代码:【点击跳转🚀】