1、说明

(1)MCU为STM32F103C8,模块为SGP30; (2)硬件连接:SGP30连接STM32的IIC1; (3)SGP30的设备地址为:(0x58<<1); (4)程序中使用HAL库,代码有CubeMX生成;

2、程序

驱动头文件:sgp30.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef __SGP30_H_
#define __SGP30_H_

#include "stdbool.h"
#include "string.h"

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

HAL_StatusTypeDef sgp30_init();
HAL_StatusTypeDef sgp30_sample(float *co2, float *tvoc);

#endif

驱动主文件:sgp30.c
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
#include "sgp30.h"
#include "i2c.h"
#include "utils.h"
#include "SEGGER_RTT.h"

#define SGP30_ADDR (0x58<<1)

//init sensor
HAL_StatusTypeDef sgp30_init()
{
uint8_t data[2];

//iaq init
data[0]=(0x2003)>>8;
data[1]=(0x2003) & 0x00FF;
return HAL_I2C_Master_Transmit(&hi2c1,SGP30_ADDR,data,2,50);
}

//get data sample
HAL_StatusTypeDef sgp30_sample(float *co2, float *tvoc)
{
uint8_t data[2];
uint8_t readbuff[6];

//measure iaq
data[0]=(0x2008)>>8;
data[1]=(0x2008) & 0x00FF;

if(HAL_I2C_Master_Transmit(&hi2c1,SGP30_ADDR,data,2,50) != HAL_OK){
SEGGER_RTT_printf(0, "write cmd m_iaq error\r\n");
return HAL_ERROR;
}

//waite data ok
int timeout = 10;
while(1){
if(HAL_I2C_Master_Receive(&hi2c1,SGP30_ADDR0x01,readbuff,6,50) != HAL_OK){
// SEGGER_RTT_printf(0, "recv data error\r\n");
timeout--;
HAL_Delay(5);
}else{
break;
}

if(timeout<=0){
return HAL_ERROR;
// break;
}
}

//check crc
if(CheckCrc8(readbuff, 0xFF) != readbuff[2] CheckCrc8(&readbuff[3], 0xFF) != readbuff[5])
{
return HAL_ERROR;
}

*co2 = (readbuff[0]<<8)readbuff[1];
*tvoc=(readbuff[3]<<8)(readbuff[4]);

return HAL_OK;
}

在main主文件进行调用:
  • 初始化
1
2
3
4
5
if(sgp30_init() != HAL_OK){
SEGGER_RTT_printf(0, "sgp30 init error\r\n");
}else{
SEGGER_RTT_printf(0, "sgp30 init ok\r\n");
}
  • 获取数据
1
2
3
4
5
6
7
8
9
if( sgp30_sample(&co2, &tvoc) != HAL_OK){
SEGGER_RTT_printf(0, "sgp30 samle error\r\n");
}

char co2str[6] = {0};
char tvocstr[6] = {0};
sprintf(co2str, "%.2f", co2);
sprintf(tvocstr, "%.2f", tvoc);
SEGGER_RTT_printf(0, "co2:%s, tvoc:%s\r\n", co2str, tvocstr);

注:在发送读取命令后,模块还不能立即返回获取的数据,因此需要做个延时。

显示结果

获取数据如下(最开始需要一定的时间等待模块初始化完成,初始化时候数据一直为400,初始化完成后数如果向模块吹气,会很明显看到CO2数据增大): SGP30结果显示