stm32毕业设计 空气质量检测系统

这篇具有很好参考价值的文章主要介绍了stm32毕业设计 空气质量检测系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1 简介

Hi,大家好,学长今天向大家介绍一个 单片机项目

基于STM32的空气质量检测仪

大家可用于 课程设计 或 毕业设计

选题指导,项目分享:
https://gitee.com/yaa-dc/warehouse-1/blob/master/iot/README.md

2 系统设计概述

如今人们大约 80%的时间是在室内度过的, 室内空气质量与我们每个人的工作和生活都息息相关, 因此对生活环境的空气质量提出了更高的要求。 针对雾霾、 室内装修等污染问题, 人们还没有有效的办法控制空气中的有害物质, 这一问题也成为人们的健康隐患, 因此对室内的空气质量进行检测至关重要。

当室内有害气体的浓度超标时, 会对人们的身心健康带来不可忽视的影响。 为了让人们及时准确地获得室内有害气体甲醛、 PM2.5 的浓度, 采取有效措施改善生活环境的空气质量, 提高工作效率。 根据我国室内空气监管标准 GB50325-2010, 学长设计了一款基于STM32F103C8T6 单片机的便携式、 低功耗室内空气质量检测仪。 该检测仪可以实时测量室内的温湿度、 甲醛浓度、 PM2.5 浓度, 并在液晶显示屏 LCD12864 上实时显示出来, 当甲醛浓度或 PM2.5 浓度超过报警值时, 测试仪通过亮红灯和蜂鸣器鸣叫的方式提醒用户室内有害气体超标。

用户可以根据需要通过 GSM 短信方式将室内空气质量情况发送到移动终端, 最后系统在 Visual Studio 2012 平台运用 C#语言开发上位机, 可以实时显示空气质量指标。

stm32毕业设计 空气质量检测系统

3 系统总体方案

学长设计为了能够实时检测室内的空气质量情况, 提高系统的稳定性和自动化程度, 将系统分为硬件设计和软件设计。 本文研制的室内 空气质 量检测仪是基于 32 位单片机STM32C8T6 进行设计的, 将整个系统模块化, 主要包括 STM32 最小系统、 温湿度检测模块、 甲醛气体检测模块、 PM2.5 检测模块、 按键、 液晶显示器、 蜂鸣器、 GSM 模块、蓝牙模块、 移动终端和上位机以及电源管理电路。 其系统结构框图如图所示。

stm32毕业设计 空气质量检测系统

在整个室内空气质量检测系统中, STM32 芯片是整个系统的主控制器, 整个检测系统都是在它的控制下完成的, 并且 STM32 为测试仪提供外部接口, 如液晶显示屏、
按键、 数据采集电路。 首先通过温湿度、 甲醛浓度以及 PM2.5 等传感器进行温湿度、 甲醛气体及 PM2.5 浓度信号采集, 再将采集到的信号送至中央处理单元 STM32 单片机进行信号转换、 放大和处理。 通过库函数编程控制检测系统的工作流程, 可以通过按键输入控制输出显示不同的测量数据以及设置甲醛和 PM2.5 浓度报警值, 当气体浓度值超过报警值时, 通过蜂鸣器鸣叫的方式提醒用户室内有害气体超标, 并在液晶屏上实时显示。利用 GSM 通信模块可以通过短信的形式将用户室内的空气质量情况发到移动终端, 实现了仪器的智能化。 STM32 最小系统通过蓝牙模块与上位机通信, 上位机可以实时显示测量数据。

4 硬件设计方案

学长设计的系统所研究的室内空气质量检测仪, 系统硬件由 STM32 单片机、 电源、 温湿度传感器、 甲醛检测模块、 PM2. 5 检测模块、 按键输入模块、 液晶显示模块、 报警电路、 GSM短信接收模块和蓝牙模块等部分组成。 该系统采用 USB 供电, 通过 USB 数据线与电脑USB 接口相连, 输出+5V 的直流电压, 输出电压在 500mA 左右, 在目前普遍采用 USB接口的情况, 这样也提高了电源的来源以及可靠性, 用户也可以通过手机充电器、 充电宝对测试仪供电, 给用户使用该测试仪带来了很大的便利 模块化的设计可以使系统设计更加简单, 系统功耗降低, 操作变得简单, 可以进行现场检测, 通过液晶显示屏用户直观地读出测量数据。 空气质量检测仪检的整体硬件设计结构如下图所示。

stm32毕业设计 空气质量检测系统

4.1 stm32 主控

STM32C8T6(最小核心板),当然,用其他型号的32,如STM32ZET6也是可以的。

stm32毕业设计 空气质量检测系统

4.2 温度采集模块

系统采用的传感器为含有已校准数字信号输出的温湿度复合传感器 DHT11。该传感器是一款已经得到业界广泛认可的安全性高、 稳定性较强、 性价比高的集中数字化传感器的温湿度。

传感器可以传输信号高达 20 米以上, 可以满足大部分场合的测量要求;具有四针的单排引脚封装系统, 这样外部连接就变得简单; 同时因其超小的体积和极低的功耗在暖通空调、 汽车、 气象站、 除湿器等各行业广泛应用。

stm32毕业设计 空气质量检测系统

4.3 甲醛浓度检测模块

综合考虑甲醛检测精度和测量成本后, 系统选用 ZE08-CH 2 O 电化学甲醛传感器检测室内空气中的甲醛浓度含量, 因该模块精度高、 功耗低,体积小的特点, 成为了制作空气质量检测仪、 空气净化器的优良器件。 相比其他甲醛

传感器主要有以下特点 :

  • (1) 分辨率和灵敏度高;
  • (2) 功耗低、 使用寿命长;
  • (2) UART、 模拟电压信号、 PWM 等多方式输出;
  • (3) 具有优秀的抗干扰性、 稳定性高;
  • (4) 内置温度补偿单元, 线性输出。

stm32毕业设计 空气质量检测系统

4.4 PM2. 5 浓度检测模块

系统选用夏普公司授权弘成基科技有限公司生产的型号为 YW-51GJ 的 PM2.5 气敏粉尘传感器, 该产品主要针对香烟颗粒、 细微颗粒等特别细微的颗粒等检测对象, 通过脉冲高度来判断细颗粒物浓度, 常用于空气净化器、 车载空气净化系统以及民用空气质量检测系统中, 符合本系统的设计要求。

YW-51GJ PM2.5 粉尘传感器实物图如图所示。

stm32毕业设计 空气质量检测系统

可以看到该 PM2.5 传感器中间有一个圆孔, 其内部安装红外线发光二极管和光电晶体管, 当微小颗粒物进入传感器的圆孔内时, 根据微小颗粒物对光的散射原理, 当细颗粒物(PM2.5) 经过传感器内部的检测孔时会对光线形成散射作用。 部分光线通过光轴,经过透镜后聚焦到感光元件上, 光信号经过感光元件转换为电信号输出。

4.5 液晶显示模块设计

stm32毕业设计 空气质量检测系统

4.6 GSM 模块

经综合考虑学长选用了 SIM800C GSM 无线通信模块, 这是 SIMCOM 公司生产的基于 MT6261 芯片平台的新一代 GSM 模块, 性价比高, 支持蓝牙功能, 支持 51、MSP430、STM32 等主流单片机开发 。

在该模块中, 通信接口为 TTL 电平串口, 引出四根排针与控制器通信。 在 IPX 天线接口连接通信天线, Micro-SIM 卡卡座可以插入移动、 联通和物联网卡, 插入 SIM 卡即可发信息给用户移动终端, SIM 卡插进去听到“咔哒” 响声表明插卡正确, SIM800C GSM 模块实物图如图所示。
stm32毕业设计 空气质量检测系统

4.7 蓝牙模块

为了能够实现测试仪与上位机的通信, 本文采用的是 HC-05 嵌入式蓝牙串口通信模块[65] , 分为两个小模块 a、 b, 如下图所示依次左右排列, 模块 a 与通过 USB 接口与电脑相连, 模块 b 通过四根排母线与测试仪对应的排针相连接。

stm32毕业设计 空气质量检测系统

为了实现主控制器 STM32 与蓝牙模块的连接, 通过导线连接对应接口, 蓝牙接口电路原理图如图所示。

stm32毕业设计 空气质量检测系统

5 软件部分设计

系统主要实现温湿度、 甲醛浓度以及 PM2.5 浓度的检测与显示功能, 通过传感器不断采集数据, 同时对这些数据进行处理、 修正和补偿, 将数据转换为温湿度以及气体浓度进行显示, 让用户可以知道室内的空气质量。 与硬件系统一样分模块设计, 软件设计分成人机交互模块和数据处理模块两部分

stm32毕业设计 空气质量检测系统

5.1 初始化

系统上电后, 先对系统的各模块传感器、 12864LCD 显示屏、 按键等外设进行初始化, 设置标志位和定时器。 之后读取温湿度、 甲醛浓度、 PM2.5 浓度对应的模拟电流电压等电信号参数值, 将数据进行 AD 转换, 对数字量处理后转换为对应的温湿度、 甲醛浓度、 PM2.5 浓度显示出来。 软件设计的主程序流程图下图所示。

stm32毕业设计 空气质量检测系统

5.2 温湿度检测程序设计

DHT11 温湿度传感器硬件设计可以知道温湿度检测电路连接十分简单,DHT11 通过引脚 2(DATA) 给 STM32 发送单总线数字信号。 在电路开始工作的时候,为了跳过不稳定状态, DHT11 需要用一秒的时间不发任何指令。
stm32毕业设计 空气质量检测系统

5.3 甲醛浓度检测程序设计

由甲醛硬件模块设计可以知道本系统采用 ZE08-CH2O 电化学甲醛传感器采集甲醛浓度信号, 利用系统 STM32 单片机自带的 2 个 AD 转换器对甲醛浓度进行采集, 这些AD 转换器具有 10 个通道, 可以单独使用, 也可以实现复用。

stm32毕业设计 空气质量检测系统

5.4 PM2. 5 浓度检测程序设计

章 PM2.5 硬件设计可以知道系统选用了 YM-51 PM2.5 传感器, 通过该模块可以对室内 PM2.5 浓度测量, 传感器通过 RXD 向 STM32 发送数据, 接线图如下所示

stm32毕业设计 空气质量检测系统

stm32毕业设计 空气质量检测系统

PM2.5 浓度检测软件程序流程与甲醛浓度检测流程类似, 首先关闭中断, 再对与PM2.5 检测模块相关的时钟、 AD 转换器进行初始化设置, 确定 AD 转换器的工作模式、触发方式等。 之后打开中断在中断服务程序中实现数据采集, 1 秒内采集 10 次, 对这些数据采用限幅平均滤波法进行软件滤波, 去除因电路干扰产生干扰有效数据的毛刺。

5.5 短信发送程序设计

章 GSM 模块硬件设计可知本文采用 SIM800C GSM 模块实现短信收发的功能。 手机短消息主要采用 PDU(协议数据单元) 模式和 TEXT 模式, PDU 模式同时支持中文和英文短信, 而 TEXT 模式只支持英文短信

stm32毕业设计 空气质量检测系统

效果展示

设计好各个模块原理图, 然后制作出 PCB 板, 通过导线将各个模块与系统主板连接, 室内空气质量检测检测仪实物图如下所示。
stm32毕业设计 空气质量检测系统

室内空气质量实时显示
stm32毕业设计 空气质量检测系统

短信收发测试
stm32毕业设计 空气质量检测系统

6 项目源码

6.1 ADC部分

 #include "adc.h"
 #include "delay.h"

//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3																	   
void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	  //使能ADC1通道时钟
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PA1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
//	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能

}				  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
  	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期	  			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 	 

6.2 DS18B20

#include "ds18b20.h"
#include "delay.h"	

//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); //SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; //拉低DQ
    delay_us(750);    //拉低750us
    DS18B20_DQ_OUT=1; //DQ=1 
	delay_us(15);     //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();//SET PA0 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) 			 // read one bit
{
    u8 data;
	DS18B20_IO_OUT();//SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();//SET PA0 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
} 
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PORTA口时钟 
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				//PORTA0 推挽输出
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOA,GPIO_Pin_0);    //输出1

	DS18B20_Rst();

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert	    
    TL=DS18B20_Read_Byte(); // LSB   
    TH=DS18B20_Read_Byte(); // MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }else temp=1;//温度为正	  	  
    tem=TH; //获得高八位
    tem<<=8;    
    tem+=TL;//获得底八位
    tem=(float)tem*0.625;//转换     
	if(temp)return tem; //返回温度值
	else return -tem;    
} 

6.3 RTC部分

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "rtc.h" 		    
//Mini STM32开发板
//RTC实时时钟 驱动代码			 
//正点原子@ALIENTEK
//2010/6/6
	   
_calendar_obj calendar;//时钟结构体 
 
static void RTC_NVIC_Config(void)
{	
    NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;		//RTC全局中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	//先占优先级1位,从优先级3位
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	//先占优先级0位,从优先级4位
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		//使能该通道中断
	NVIC_Init(&NVIC_InitStructure);		//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}

//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码

u8 RTC_Init(void)
{
	//检查是不是第一次配置时钟
	u8 temp=0;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	//使能PWR和BKP外设时钟   
	PWR_BackupAccessCmd(ENABLE);	//使能后备寄存器访问  
	if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)		//从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
		{	 			

		BKP_DeInit();	//复位备份区域 	
		RCC_LSEConfig(RCC_LSE_ON);	//设置外部低速晶振(LSE),使用外设低速晶振
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)	//检查指定的RCC标志位设置与否,等待低速晶振就绪
			{
			temp++;
			delay_ms(10);
			}
		if(temp>=250)return 1;//初始化时钟失败,晶振有问题	    
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);		//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    
		RCC_RTCCLKCmd(ENABLE);	//使能RTC时钟  
		RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成
		RTC_WaitForSynchro();		//等待RTC寄存器同步  
		RTC_ITConfig(RTC_IT_SEC, ENABLE);		//使能RTC秒中断
		RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成
		RTC_EnterConfigMode();/// 允许配置	
		RTC_SetPrescaler(32767); //设置RTC预分频的值
		RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成
		RTC_Set(2020,5,5,12,59,00);  //设置时间	
		RTC_ExitConfigMode(); //退出配置模式  
		BKP_WriteBackupRegister(BKP_DR1, 0X5050);	//向指定的后备寄存器中写入用户程序数据
		}
	else//系统继续计时
		{

		RTC_WaitForSynchro();	//等待最近一次对RTC寄存器的写操作完成
		RTC_ITConfig(RTC_IT_SEC, ENABLE);	//使能RTC秒中断
		RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成
		}
	RTC_NVIC_Config();//RCT中断分组设置		    				     
	RTC_Get();//更新时间	
	return 0; //ok

}		 				    
//RTC时钟中断
//每秒触发一次  
//extern u16 tcnt; 
void RTC_IRQHandler(void)
{		 
	if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断
	{							
		RTC_Get();//更新时间   
 	}
	if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断
	{
		RTC_ClearITPendingBit(RTC_IT_ALR);		//清闹钟中断	  	   
  	} 				  								 
	RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);		//清闹钟中断
	RTC_WaitForLastTask();	  	    						 	   	 
}
//判断是否是闰年函数
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//闰年   31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{			  
	if(year%4==0) //必须能被4整除
	{ 
		if(year%100==0) 
		{ 
			if(year%400==0)return 1;//如果以00结尾,还要能被400整除 	   
			else return 0;   
		}else return 1;   
	}else return 0;	
}	 			   
//设置时钟
//把输入的时钟转换为秒钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//返回值:0,成功;其他:错误代码.
//月份数据表											 
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表	  
//平年的月份日期表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
	u16 t;
	u32 seccount=0;
	if(syear<1970||syear>2099)return 1;	   
	for(t=1970;t<syear;t++)	//把所有年份的秒钟相加
	{
		if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
		else seccount+=31536000;			  //平年的秒钟数
	}
	smon-=1;
	for(t=0;t<smon;t++)	   //把前面月份的秒钟数相加
	{
		seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
		if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数	   
	}
	seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 
	seccount+=(u32)hour*3600;//小时秒钟数
    seccount+=(u32)min*60;	 //分钟秒钟数
	seccount+=sec;//最后的秒钟加上去

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	//使能PWR和BKP外设时钟  
	PWR_BackupAccessCmd(ENABLE);	//使能RTC和后备寄存器访问 
	RTC_SetCounter(seccount);	//设置RTC计数器的值

	RTC_WaitForLastTask();	//等待最近一次对RTC寄存器的写操作完成  	
	RTC_Get();
	return 0;	    
}
//得到当前的时间
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{
	static u16 daycnt=0;
	u32 timecount=0; 
	u32 temp=0;
	u16 temp1=0;	  
    timecount=RTC_GetCounter();	 
 	temp=timecount/86400;   //得到天数(秒钟数对应的)
	if(daycnt!=temp)//超过一天了
	{	  
		daycnt=temp;
		temp1=1970;	//从1970年开始
		while(temp>=365)
		{				 
			if(Is_Leap_Year(temp1))//是闰年
			{
				if(temp>=366)temp-=366;//闰年的秒钟数
				else {temp1++;break;}  
			}
			else temp-=365;	  //平年 
			temp1++;  
		}   
		calendar.w_year=temp1;//得到年份
		temp1=0;
		while(temp>=28)//超过了一个月
		{
			if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
			{
				if(temp>=29)temp-=29;//闰年的秒钟数
				else break; 
			}
			else 
			{
				if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
				else break;
			}
			temp1++;  
		}
		calendar.w_month=temp1+1;	//得到月份
		calendar.w_date=temp+1;  	//得到日期 
	}
	temp=timecount%86400;     		//得到秒钟数   	   
	calendar.hour=temp/3600;     	//小时
	calendar.min=(temp%3600)/60; 	//分钟	
	calendar.sec=(temp%3600)%60; 	//秒钟
	calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期   
	return 0;
}	 
//获得现在是星期几
//功能描述:输入公历日期得到星期(只允许1901-2099年)
//输入参数:公历年月日 
//返回值:星期号																						 
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{	
	u16 temp2;
	u8 yearH,yearL;
	
	yearH=year/100;	yearL=year%100; 
	// 如果为21世纪,年份数加100  
	if (yearH>19)yearL+=100;
	// 所过闰年数只算1900年之后的  
	temp2=yearL+yearL/4;
	temp2=temp2%7; 
	temp2=temp2+day+table_week[month-1];
	if (yearL%4==0&&month<3)temp2--;
	return(temp2%7);
}			  

6.4 main部分

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "math.h"
#include "ds18b20.h"  
#include "rtc.h"

   	
 int main(void)
 { 
	u16 adcx;
	float temp,quality;
	short temperature; 
	u8 t;	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 
	 
	delay_init();	    	 //延时函数初始化	  
	uart_init(9600);	 	 //串口初始化为9600
	LED_Init();		  		 //初始化与LED连接的硬件接口
 	LCD_Init();
 	Adc_Init();		  		//ADC初始化	

	POINT_COLOR=BLACK; 
	LCD_DrawLine(0,80,240,80);
	LCD_DrawLine(120,80,120,240);
	LCD_DrawLine(0,240,240,240);
	LCD_DrawLine(0,280,240,280);
	LCD_DrawLine(120,120,120,240);
	LCD_DrawLine(120,160,240,160); 
	LCD_ShowString(40,20,230,16,16,"AIR MONITIRING SYSTEM");
	LCD_ShowString(76,40,230,16,16,"BASED ON RTOS");
	LCD_ShowString(10,100,230,16,16,"AIR QUALITY:");
	LCD_ShowString(130,90,230,16,16,"HARMFUL GAS");
	LCD_ShowString(125,110,230,16,16,"CONCENTRATION:");
	LCD_ShowString(150,130,230,16,16,"     PPM");  
	LCD_ShowString(130,170,230,16,16,"TEMPERATURE:");  
	LCD_ShowString(150,190,230,16,16,"   . C"); 	
	//LCD_ShowString(10,250,200,16,16,"2020-4-30 16:00");	
	LCD_ShowString(10,290,200,16,16,"STM32F103,MQ135,DS18B20");	
	
	while(DS18B20_Init())	//DS18B20初始化	
	{
		LCD_ShowString(150,210,200,16,16,"DS18B20 Error");
		delay_ms(200);
		LCD_Fill(60,130,239,130+16,WHITE);
 		delay_ms(200);
	}
		
	while(RTC_Init())		//RTC初始化	,一定要初始化成功
	{ 
		LCD_ShowString(10,250,200,16,16,"RTC ERROR!   ");	
		delay_ms(800);
		LCD_ShowString(10,250,200,16,16,"RTC Trying...");	
	}		    						
	//显示时间				 
	LCD_ShowString(10,250,200,16,16,"    -  -  ");	   
	LCD_ShowString(100,250,200,16,16,"  :  :  ");	 	
	//显示提示信息
	//LCD_ShowString(60,130,200,16,16,"ADC_CH1_VAL:");	      
	//LCD_ShowString(60,150,200,16,16,"ADC_CH1_VOL:0.000V");	
    //LCD_ShowString(60,170,200,16,16,"KQ_ZHILIANG:    ppm");	
   	 
	while(1)
	{
		
		adcx=Get_Adc_Average(ADC_Channel_1,10);
		//LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
		temp=(float)adcx*(3.3/4096);
		quality=pow((11.5428 * 35.904 * temp )/(25.5 - 5.1 * temp),1.0/0.6549);
		adcx=temp;
		//LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
		temp-=adcx;
		//temp*=1000;
		//LCD_ShowxNum(172,150,temp,3,16,0X80);
		LCD_ShowxNum(150,130,quality,4,16,0);//显示转化后的PPM值
		//根据有害气体浓度判断空气质量
		if(0<= quality && quality <=75)
			LCD_ShowString(20,150,200,16,24,"NORMAL");	
		else if(quality<=150)
			LCD_ShowString(20,150,200,16,24,"MILD  ");
		else if(quality<=500)
			LCD_ShowString(20,150,200,16,24,"MIDDLE");
		else 
			LCD_ShowString(20,150,200,16,24,"SEVERE");
	
		
		temperature=DS18B20_Get_Temp();	
		if(temperature<0)
		{
			LCD_ShowChar(60+40,150,'-',16,0);			//显示负号
			temperature=-temperature;					//转为正数
		}else LCD_ShowChar(60+40,150,' ',16,0);			//去掉负号
		LCD_ShowNum(150+8,190,temperature/10,2,16);	//显示正数部分	    
   		LCD_ShowNum(150+32,190,temperature%10,1,16);	//显示小数部分
		
		//LCD_ShowString(170,190,290,16,16,"26");//显示温度
		
		if(quality>=150) //当到达中度污染时红灯闪烁报警
		{
			LED1=1;
			LED0=!LED0;
			POINT_COLOR=RED;//设置字体为红色 
		}
		else
		{
			LED0=1;
			LED1=!LED1;  //正常时绿灯闪烁
			POINT_COLOR=BLUE;//设置字体为蓝色 
		}
		
		//显示时间
		if(t!=calendar.sec)
		{
			POINT_COLOR=BLACK;//设置字体为黑色
			t=calendar.sec;
			LCD_ShowNum(10,250,calendar.w_year,4,16);									  
			LCD_ShowNum(50,250,calendar.w_month,2,16);									  
			LCD_ShowNum(74,250,calendar.w_date,2,16);	 
			
			LCD_ShowNum(100,250,calendar.hour,2,16);									  
			LCD_ShowNum(124,250,calendar.min,2,16);									  
			LCD_ShowNum(148,250,calendar.sec,2,16);
			switch(calendar.week)
			{
				case 0:
					LCD_ShowString(170,250,200,16,16,"Sunday");
					break;
				case 1:
					LCD_ShowString(170,250,200,16,16,"Monday");
					break;
				case 2:
					LCD_ShowString(170,250,200,16,16,"Tuesday");
					break;
				case 3:
					LCD_ShowString(170,250,200,16,16,"Wednesday");
					break;
				case 4:
					LCD_ShowString(170,250,200,16,16,"Thursday");
					break;
				case 5:
					LCD_ShowString(170,250,200,16,16,"Friday");
					break;
				case 6:
					LCD_ShowString(60,148,200,16,16,"Saturday ");
					break;  
			}
		}
		delay_ms(200);	
	}											    
}	


选题指导,项目分享:
https://gitee.com/yaa-dc/warehouse-1/blob/master/iot/README.md文章来源地址https://www.toymoban.com/news/detail-430849.html

到了这里,关于stm32毕业设计 空气质量检测系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32CubMX_MQ135检测空气质量

    MQ135 是测量空气污染情况常用的一个传感器,具有代表性,价格低,寿命长,敏感度也OK,主要用于测量空气中二氧化碳,氮氧化物,氨气,酒精,苯类等。这几样气体可以说都属于家用空气污染测定中的重要成份,因此用这个传感器刚刚好。 MQ135 气体传感器所使用的气敏材

    2023年04月12日
    浏览(37)
  • 【STM32外设系列】JW01三合一空气质量检测模块

    🎀 文章作者:二土电子 🌸 关注公众号获取更多资料! 🐸 期待大家一起学习交流!   首先我们看一下JW01的样子   值得注意的是,本文介绍的是三合一空气质量检测模块,能够检测空气中有机气态物质的浓度,同时也能检测甲醛和二氧化碳的浓度,该模块通过串口输

    2024年02月04日
    浏览(52)
  • 基于单片机的室内空气质量监控系统设计

    摘 要 I Abstract II 引 言 1 1 控制系统设计 3 1.1 方案选择 3 1.2 系统控制原理 4 2系统硬件设计 5 2.1 单片机的选择与设计 5 2.2 温湿度模块设计 6 2.3 甲醛采集模块设计 8 2.4 显示器模块设计 9 2.5 按键模块设计 10 2.6 报警模块设计 11 2.7 加湿及风扇模块设计 11 3系统软件设计 13 3.1 总流

    2024年03月16日
    浏览(58)
  • 毕业设计 基于STM32的环境质量监测系统(源码+原理图+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月02日
    浏览(47)
  • 物联网毕业设计 基于STM32的环境质量监测系统(源码+原理图+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月07日
    浏览(58)
  • 【特纳斯电子】基于单片机的空气质量检测仪-实物设计

    资料查找方式: 特纳斯电子(电子校园网):搜索下面编号即可 T2212204C-SW 本设计是基于单片机的空气质量检测仪,主要实现以下功能: 1.可以通过显示屏来显示温度、湿度、PM2.5浓度、一氧化碳浓值。 2.通过温湿度模块来检测环境温度湿度值。 3.通过PM2.5检测器来检测PM2.5值

    2024年02月19日
    浏览(51)
  • python上海空气质量数据可视化大屏全屏系统设计与实现(django框架)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月03日
    浏览(45)
  • python天津空气质量数据可视化大屏全屏系统设计与实现(django框架)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月03日
    浏览(51)
  • python湖南长沙空气质量数据可视化大屏全屏系统设计与实现(django框架)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月04日
    浏览(47)
  • python福建福州空气质量数据可视化大屏全屏系统设计与实现(django框架)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月04日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包