SGP30气体传感器详解 (STM32)
目录
一、介绍
二、传感器原理
原理图
三、程序设计
main.c文件
sgp30.c文件
sgp30.h文件
四、实验效果
五、资料获取
项目分享
一、介绍
SGP30是一种室内空气质量传感器,能够检测二氧化碳(CO2)和挥发性有机化合物(VOC)的浓度。这个模块采用了先进的传感器技术,可以提供高精度的空气质量数据。SGP30模块通常包括一个集成的传感器芯片和相应的电路,使其能够方便地与微控制器连接。它通常通过I2C总线与微控制器通信,因此可以轻松地集成到各种不同的嵌入式系统中。
以下是气体传感器的参数:
哔哩哔哩视频链接:
SGP30气体传感器(二氧化碳 STM32)
(资料分享见文末)
二、传感器原理
原理图
三、程序设计
1.使用STM32F103C8T6读取SGP30气体传感器采集的二氧化碳数据,通过串口发送至电脑
2.将读取得到信息数据同时在OLED上显示
main.c文件
#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "sgp30.h"/*****************辰哥单片机设计******************STM32* 项目 : SGP30气体传感器实验 * 版本 : V1.0* 日期 : 2025.8.1* MCU : STM32F103C8T6* 接口 : 参看sgp30.h * BILIBILI : 辰哥单片机设计* CSDN : 辰哥单片机设计* 作者 : 辰哥 **********************BEGIN***********************/uint16_t co2_value = 0; //co2值
u8 buff[30];//参数显示缓存数组int main(void){ SystemInit();//配置系统时钟为72M delay_init(72);LED_Init();LED_On();SGP30_Init();USART1_Config();//串口初始化OLED_Init();printf("Start \n");delay_ms(1000);OLED_Clear();//显示“二氧化碳:”OLED_ShowChinese(0,0,0,16,1);OLED_ShowChinese(16,0,1,16,1);OLED_ShowChinese(32,0,2,16,1);OLED_ShowChinese(48,0,3,16,1);OLED_ShowChar(64,0,':',16,1);while (1){LED_Toggle();Sgp30_Get_Co2_Value(&co2_value); OLED_ShowNum(40,20,co2_value,3,16,1);OLED_ShowString(70,20,"ppm",16,1);delay_ms(100); //延时100ms}
}
sgp30.c文件
#include "sgp30.h"
#include "delay.h"/*****************辰哥单片机设计******************STM32* 文件 : SGP30气体传感器c文件 * 版本 : V1.0* 日期 : 2025.8.1* MCU : STM32F103C8T6* 接口 : 见代码 * BILIBILI : 辰哥单片机设计* CSDN : 辰哥单片机设计* 作者 : 辰哥**********************BEGIN***********************/void SGP30_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(SGP30_IIC_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = SGP30_IIC_SCL_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SGP30_IIC_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = SGP30_IIC_SDA_PIN;GPIO_Init(SGP30_IIC_PORT, &GPIO_InitStructure);
}void SDA_OUT(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SGP30_IIC_SDA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SGP30_IIC_PORT, &GPIO_InitStructure);
}void SDA_IN(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SGP30_IIC_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(SGP30_IIC_PORT, &GPIO_InitStructure);
}//产生IIC起始信号
void SGP30_IIC_Start(void)
{SDA_OUT();SGP30_IIC_SDA = 1;SGP30_IIC_SCL = 1;delay_us(20);SGP30_IIC_SDA = 0; //START:when CLK is high,DATA change form high to lowdelay_us(20);SGP30_IIC_SCL = 0; //钳住I2C总线,准备发送或接收数据
}//产生IIC停止信号
void SGP30_IIC_Stop(void)
{SDA_OUT();SGP30_IIC_SCL = 0;SGP30_IIC_SDA = 0; //STOP:when CLK is high DATA change form low to highdelay_us(20);SGP30_IIC_SCL = 1;SGP30_IIC_SDA = 1; //发送I2C总线结束信号delay_us(20);
}//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 SGP30_IIC_Wait_Ack(void)
{u8 ucErrTime = 0;SDA_IN();SGP30_IIC_SDA = 1;delay_us(10);SGP30_IIC_SCL = 1;delay_us(10);while(SGP30_READ_SDA){ucErrTime++;if(ucErrTime > 250){SGP30_IIC_Stop();return 1;}}SGP30_IIC_SCL = 0; //时钟输出0return 0;
}//产生ACK应答
void SGP30_IIC_Ack(void)
{SGP30_IIC_SCL = 0;SDA_OUT();SGP30_IIC_SDA = 0;delay_us(20);SGP30_IIC_SCL = 1;delay_us(20);SGP30_IIC_SCL = 0;
}//不产生ACK应答
void SGP30_IIC_NAck(void)
{SGP30_IIC_SCL = 0;SDA_OUT();SGP30_IIC_SDA = 1;delay_us(20);SGP30_IIC_SCL = 1;delay_us(20);SGP30_IIC_SCL = 0;
}//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void SGP30_IIC_Send_Byte(u8 txd)
{u8 t;SDA_OUT();SGP30_IIC_SCL = 0; //拉低时钟开始数据传输for(t = 0; t < 8; t++){if((txd & 0x80) >> 7)SGP30_IIC_SDA = 1;elseSGP30_IIC_SDA = 0;txd <<= 1;delay_us(20);SGP30_IIC_SCL = 1;delay_us(20);SGP30_IIC_SCL = 0;delay_us(20);}delay_us(20);}//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u16 SGP30_IIC_Read_Byte(u8 ack)
{u8 i;u16 receive = 0;SDA_IN();for(i = 0; i < 8; i++ ){SGP30_IIC_SCL = 0;delay_us(20);SGP30_IIC_SCL = 1;receive <<= 1;if(SGP30_READ_SDA)receive++;delay_us(20);}if (!ack)SGP30_IIC_NAck();//发送nACKelseSGP30_IIC_Ack(); //发送ACKreturn receive;
}//初始化IIC接口
void SGP30_Init(void)
{SGP30_GPIO_Init();SGP30_Write(0x20, 0x03);
}void SGP30_Write(u8 a, u8 b)
{SGP30_IIC_Start();SGP30_IIC_Send_Byte(SGP30_write); //发送器件地址+写指令SGP30_IIC_Wait_Ack();SGP30_IIC_Send_Byte(a); //发送控制字节SGP30_IIC_Wait_Ack();SGP30_IIC_Send_Byte(b);SGP30_IIC_Wait_Ack();SGP30_IIC_Stop();delay_ms(100);
}u32 SGP30_Read(void)
{u32 dat;u8 crc;SGP30_IIC_Start();SGP30_IIC_Send_Byte(SGP30_read); //发送器件地址+读指令SGP30_IIC_Wait_Ack();dat = SGP30_IIC_Read_Byte(1);dat <<= 8;dat += SGP30_IIC_Read_Byte(1);crc = SGP30_IIC_Read_Byte(1); //crc数据,舍去crc = crc; //为了不让出现编译警告dat <<= 8;dat += SGP30_IIC_Read_Byte(1);dat <<= 8;dat += SGP30_IIC_Read_Byte(0);SGP30_IIC_Stop();return(dat);
}
/****
*******SGP30获取CO2和TVOC值函数
*****/
void Sgp30_Get_Co2_Value(u16 *co2_value)
{u32 sgp30_data = 0;SGP30_Write(0x20,0x08);sgp30_data = SGP30_Read();if(sgp30_data != 0x01900000){*co2_value = (sgp30_data & 0xffff0000)>>16;}
}
sgp30.h文件
#ifndef __SGP30_H
#define __SGP30_H
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"/*****************辰哥单片机设计******************STM32* 文件 : SGP30二氧化碳传感器h文件 * 版本 : V1.0* 日期 : 2025.8.1* MCU : STM32F103C8T6* 接口 : 见代码 * BILIBILI : 辰哥单片机设计* CSDN : 辰哥单片机设计* 作者 : 辰哥**********************BEGIN***********************//***************根据自己需求更改****************/
// SGP30 GPIO宏定义#define SGP30_IIC_CLK RCC_APB2Periph_GPIOA
#define SGP30_IIC_PORT GPIOA
#define SGP30_IIC_SCL_PIN GPIO_Pin_6
#define SGP30_IIC_SDA_PIN GPIO_Pin_7 //IO操作函数
#define SGP30_IIC_SCL PAout(6) //SCL
#define SGP30_IIC_SDA PAout(7) //SDA
#define SGP30_READ_SDA PAin(7) //输入SDA /*********************END**********************/#define SGP30_read 0xb1 //SGP30的读地址
#define SGP30_write 0xb0 //SGP30的写地址//SGP30
void SGP30_IIC_Start(void); //发送IIC开始信号
void SGP30_IIC_Stop(void); //发送IIC停止信号
void SGP30_IIC_Send_Byte(u8 txd); //IIC发送一个字节
u16 SGP30_IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
u8 SGP30_IIC_Wait_Ack(void); //IIC等待ACK信号
void SGP30_IIC_Ack(void); //IIC发送ACK信号
void SGP30_IIC_NAck(void); //IIC不发送ACK信号
void SGP30_IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 SGP30_IIC_Read_One_Byte(u8 daddr,u8 addr);
void SGP30_Init(void);
void SGP30_Write(u8 a, u8 b);
u32 SGP30_Read(void);
void Sgp30_Get_Co2_Value(u16 *co2_value);#endif