目录
一、前言
项目成品图片:
哔哩哔哩视频链接:
STM32矿井环境监测系统/粉尘监测
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的矿井环境监测系统
功能如下:
- STM32F103C8T6单片机作为主控制器
- DS18B20测量环境温度,当温度不在设置的上下限,则声光报警
- PM2.5传感器测量粉尘浓度,当浓度大于设定最大值,则声光报警,并自动喷雾
- 可通过按键设置各阈值
- 通过OLED显示屏显示测量值
- 通过蓝牙可手机端接收数据,保存数据,手机端可远程开关喷雾
2.主要器件
- STM32F103C8T6单片机
- OLED 屏幕
- DS18B20温度传感器
- 粉尘传感器
- BT04A蓝牙模块
- 继电器
- 有源蜂鸣器
- 加湿器
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "adc.h"
#include "pm25.h"
#include "ds18b20.h"
/**********************************
变量定义
**********************************/
uint8_t key_num = 0; //按键扫描标志位
uint8_t flag_display = 0; //显示界面标志位
uint32_t time_num = 0; //10ms计时
short temp_value = 0; //温度值
u16 temp_max = 40; //温度最大值
u16 temp_min = 10; //温度最小值
u16 pm25_value = 0; //粉尘值
u16 pm25_max = 200; //粉尘最大值
_Bool flag_mode = 0; //模式标志位
extern uint8_t usart1_buf[256]; //串口1接收数组
char display_buf[32]; //显示缓存区
/**********************************
函数声明
**********************************/
void Key_function(void); //按键函数
void Monitor_function(void); //监测函数
void Display_function(void); //显示函数
void Manage_function(void); //处理函数
/****
******* 主函数
*****/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组
Delay_Init(); //延时初始化
Gpio_Init(); //IO初始化
Key_Init(); //按键初始化
Oled_Init(); //OLED初始化
Oled_Clear_All(); //清屏
Usart1_Init(9600); //串口1初始化
PM25_Init(); //PM2.5初始化
Adc_Init(); //ADC初始化
DS18B20_Init(); //w温度初始化
while(1)
{
Key_function(); //按键函数
Monitor_function(); //监测函数
Display_function(); //显示函数
Manage_function(); //处理函数
time_num++; //计时变量+1
Delay_ms(10);
if(time_num %10 == 0)
LED_SYS = ~LED_SYS;
if(time_num >= 5000)
{
time_num = 0;
}
}
}
/****
*******按键函数
*****/
void Key_function(void)
{
key_num = Chiclet_Keyboard_Scan(0); //按键扫描
if(key_num != 0) //有按键按下
{
switch(key_num)
{
case 1: //按键1,切换设置界面
flag_display++;
if(flag_display >= 4)
flag_display = 0;
Oled_Clear_All(); //清屏
break;
case 2: //按键2
switch(flag_display)
{
case 0: //界面0:
break;
case 1: //界面1:温度最大值+1
if(temp_max < 99)
temp_max++;
break;
case 2: //界面2:温度最小值+1
if(temp_min < temp_max-1)
temp_min++;
break;
case 3: //界面3:
if(pm25_max < 650)
pm25_max++;
break;
default:
break;
}
break;
case 3: //按键3
switch(flag_display)
{
case 0: //界面0:
break;
case 1: //界面1:温度最大值-1
if(temp_max > temp_min+1)
temp_max--;
break;
case 2: //界面2:温度最小值-1
if(temp_min > 0)
temp_min--;
break;
case 3: //界面3:
if(pm25_max > 0)
pm25_max--;
break;
default:
break;
}
break;
default:
break;
}
}
}
/****
*******监测函数
*****/
void Monitor_function(void)
{
if(flag_display == 0) //测量界面
{
pm25_value = Pm25_Get_Value(3); //获取PM2.5
temp_value = DS18B20_Get_Temp();
if(time_num % 30 == 0) //发送数据
{
UsartPrintf(USART1,"温度:%d.%dC\r\n",temp_value/10,temp_value%10);
UsartPrintf(USART1,"粉尘:%dppm\r\n",pm25_value);
}
if(USART1_WaitRecive() == 0) //如果接收到蓝牙数据
{
switch(usart1_buf[0])
{
case('A'): //A:切换自动模式
flag_mode = 0;
break;
case('B'): //B:
RELAY_JS = ~RELAY_JS;
flag_mode = 1;
break;
default:
break;
}
USART1_Clear();
}
}
}
/****
*******显示函数
*****/
void Display_function(void)
{
switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
{
case 0: //界面0:
Oled_ShowCHinese(1,0,"温度:");
sprintf(display_buf,"%d.%dC ",temp_value/10,temp_value%10);
Oled_ShowString(1, 6, display_buf);
Oled_ShowCHinese(2,0,"粉尘:");
sprintf(display_buf,"%dppm ",pm25_value);
Oled_ShowString(2, 6, display_buf);
if(flag_mode == 0) //显示模式
Oled_ShowCHinese(3, 0, "模式:自动");
else
Oled_ShowCHinese(3, 0, "模式:手动");
break;
case 1: //界面1:显示设置温度最大值
Oled_ShowCHinese(1,0,"设置温度最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_max);
Oled_ShowString(2, 6, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 6, " ");
}
break;
case 2: //界面2:显示设置温度最小值
Oled_ShowCHinese(1,0,"设置温度最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_min);
Oled_ShowString(2, 6, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 6, " ");
}
break;
case 3: //界面3:
Oled_ShowCHinese(1,0,"设置粉尘最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",pm25_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
default:
break;
}
}
/****
*******处理函数
*****/
void Manage_function(void)
{
if(flag_display == 0) //测量界面
{
if(flag_mode == 0)
{
if(pm25_value > pm25_max || temp_value > temp_max*10 || temp_value < temp_min*10) //声光报警
{
if(time_num % 3 == 0)
{
BEEP =~BEEP;
LED =~ LED;
}
}
else
{
BEEP = 0;
LED = 1;
}
if(pm25_value > pm25_max)
{
RELAY_JS = 1;
}
else
{
RELAY_JS = 0;
}
}
}
else //设置界面
{
RELAY_JS = 0;
BEEP = 0;
LED = 1;
}
}
六、实验效果
七、资料内容