欢迎光临
我们一直在努力

STM32项目开源:粮仓环境安防监测系统(代码 + 原理图 + 仿真)

文章目录

  • 一、前言
  • 二、项目功能简介
  • 三、PCB设计
  • 四、原理图设计
  • 五、程序设计
  • 六、包含内容
  • 七、资料分享

一、前言

实物项目成品: 在这里插入图片描述

仿真项目成品: 在这里插入图片描述

哔哩哔哩开源视频链接(复制浏览器打开): https://www.bilibili.com/video/BV1KuYy6DEKd/?vd_source=10da4d04d580bd6b34f7298120737c50

(资料分享见文末)

二、项目功能简介

【开源】STM32单片机粮仓环境安防监测系统(代码 + 原理图 + 仿真)-编号:CY26042 功能介绍: (1)多参数监测:实时采集粮仓温湿度、光照强度、二氧化碳、烟雾、甲醛有毒气体浓度。 (2)OLED 显示:OLED 屏幕实时展示各项采集数据。 (3)超限联动:参数超过阈值,蜂鸣器报警,自动开启风扇排湿排气,APP 同步告警。 (4)防火监测:检测到火苗触发蜂鸣器报警,APP 推送火情提醒。 (5)防盗监测:检测到人员入侵,触发报警,APP 推送防盗提醒。 (6)按键设参:本地按键可修改各项参数安全阈值。 (7)APP 设参:手机 APP 远程设置各项安全阈值。 (8)APP 远程控制:APP 实时查看监测数据,可手动控制风扇开关。

三、PCB设计

在这里插入图片描述

四、原理图设计

在这里插入图片描述

五、程序设计

代码如下():

#include "stm32f10x.h" // Device header
#include "iwdg.h"
#include "adcx.h"
#include "ldr.h"
#include "oled.h"
#include "dht11.h"
#include "led.h"
#include "key.h"
#include "tim2.h"
#include "tim3.h"
#include "usart3.h"
#include "usart.h"
#include "yl_69.h"
#include "motor.h"
#include "sensormodules.h"
#include "flash.h"
#include "esp8266.h"
#include "stdio.h"
#include <string.h>
#include "stdarg.h"
#include "stdlib.h"
#include <stdlib.h>
#include <stdbool.h>
#define KEY_11
#define KEY_22
#define KEY_33
#define KEY_44

#define FLASH_START_ADDR0x0801f000//写入的起始地址

SensorModules sensorData;//声明传感器数据结构体变量
SensorThresholdValue Sensorthreshold;//声明传感器阈值结构体变量

uint8_t menu = 1;//显示菜单变量
uint8_t OLED_Clear_Flag;//阈值设置界面的清屏标志位
uint8_t sendFlag=0;
unsigned char SendString[30];//向蓝牙发送的显示信息
uint8_t count = 1;
uint8_t SDflag = 0;
extern u8 shuaxing;
extern vu16 USART1_RX_STA;
extern const unsigned char BMP[];
extern const unsigned char BMP25[];

uint8_t beepflag1,beepflag2,beepflag3,beepflag4,beepflag5,beepflag6;
enum
{
display_page1 = 1, //主界面-
settingsPage //设置界面

}MenuPages;

// 改进的mid函数,增加安全性检查
char * mid(char *dst, size_t dst_size, char *src, int n, int m)
{
if (dst == NULL || src == NULL || dst_size == 0) {
return NULL;
}

int len = strlen(src);

// 调整参数确保在有效范围内
if (m < 0) m = 0;
if (m > len) return NULL;
if (n > len m) n = len m;
if (n >= dst_size) n = dst_size 1; // 保留空间给null终止符

char *p = src + m;
char *q = dst;

while (n > 0) {
*(q++) = *(p++);
}
*q = '\\0'; // 添加字符串终止符

return dst;
}

// 辅助函数:从字符串中提取数字值
int extract_value(char *data_ptr, const char *prefix)
{
if (data_ptr == NULL) return 0;

int prefix_len = strlen(prefix);
char *value_ptr = data_ptr + prefix_len;
char dest[32] = {0};
int i = 0;

// 跳过可能存在的空格
while (*value_ptr == ' ') value_ptr++;

// 提取数字部分
while (*value_ptr >= '0' && *value_ptr <= '9' && i < sizeof(dest)1) {
dest[i++] = *value_ptr++;
}
dest[i] = '\\0';

return (strlen(dest) > 0) ? atoi(dest) : 0;
}
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{
unsigned short count = 0;

for(; count < len; count++)
{
USART_SendData(USARTx, *str++);//发送数据
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);//等待发送完成
}

}
void Bluetooth_Analyse(void)
{
if(USART1_RX_STA == 1)
{
// 查找温度数据
char* temp_ptr = strstr((const char*)USART1_RX_BUF, "temp:");
if(temp_ptr != NULL)
{
Sensorthreshold.tempValue = extract_value(temp_ptr, "temp:");
}
// 查找湿度数据
char* humi_ptr = strstr((const char*)USART1_RX_BUF, "humi:");
if(humi_ptr != NULL)
{
Sensorthreshold.humiValue = extract_value(humi_ptr, "humi:");
}
// 查找光照数据
char* GZ_ptr = strstr((const char*)USART1_RX_BUF, "light:");
if(GZ_ptr != NULL)
{
Sensorthreshold.luxValue = extract_value(GZ_ptr, "light:");
}
// 查找CO2数据
char* CO2_ptr = strstr((const char*)USART1_RX_BUF, "co2:");
if(CO2_ptr != NULL)
{
Sensorthreshold.CO2Value = extract_value(CO2_ptr, "co2:");
}
// 查找烟雾数据
char* MQ2_ptr = strstr((const char*)USART1_RX_BUF, "yanwu:");
if(MQ2_ptr != NULL)
{
Sensorthreshold.MQ2Value = extract_value(MQ2_ptr, "yanwu:");
}
// 清空缓冲区
memset(USART1_RX_BUF, 0, sizeof(USART1_RX_BUF));
USART1_RX_Count = 0;
USART1_RX_STA = 0;
}
if(sendFlag==1) //800ms上传一次数据
{
sendFlag = 0;
SendString[0]='m';
SendString[1]='s';
SendString[2]='g';
SendString[3]='=';
SendString[4]='#';
SendString[5]=sensorData.temp /10+'0';
SendString[6]=sensorData.temp %10+'0';
SendString[7]='#';

SendString[8]=sensorData.humi/10+'0';
SendString[9]=sensorData.humi%10+'0';
SendString[10]='#';

SendString[11]=sensorData.lux/1000+'0';
SendString[12]=sensorData.lux%1000/100+'0';
SendString[13]=sensorData.lux%1000%100/10+'0';
SendString[14]=sensorData.lux%10+'0';
SendString[15]='#';

SendString[16]=sensorData.CO2/1000+'0';
SendString[17]=sensorData.CO2%1000/100+'0';
SendString[18]=sensorData.CO2%1000%100/10+'0';
SendString[19]=sensorData.CO2%10+'0';
SendString[20]='#';

SendString[21]=sensorData.MQ2/10+'0';
SendString[22]=sensorData.MQ2%10+'0';
SendString[23]='#';
if(huo==1)
SendString[24]=1+'0';
else
SendString[24]=0+'0';
SendString[25]='#';
Usart_SendString(USART1,SendString,26);
}
}
/**
* @brief 显示菜单1的固定内容
* @param 无
* @retval 无
*/

void OLED_Menu1(void)
{
static uint8_t crl_flag1=0,crl_flag2=0;
if(huo == 1||men==1) //检测到火焰
{
if(crl_flag2==1)
{
crl_flag2=0;
OLED_Clear();
}
Delay_ms(10);
if(huo == 1)
{
OLED_DrawBMP(48,1,80,5,(unsigned char *)BMP); //显示火焰图片
OLED_ShowChinese(4, 2, 55);
OLED_ShowChinese(4, 3, 56);
OLED_ShowChinese(4, 4, 57);
OLED_ShowChinese(4, 5, 58);
OLED_ShowChinese(4, 6, 59);
OLED_ShowChinese(4, 7, 60);
}
if(men == 1)
{
OLED_DrawBMP(64,0,104,8,(unsigned char *)BMP25);
OLED_ShowChinese(1, 2, 61);
OLED_ShowChinese(1, 3, 62);
OLED_ShowChinese(2, 1, 63);
OLED_ShowChinese(2, 2, 64);
OLED_ShowChinese(2, 3, 65);
OLED_ShowChinese(2, 4, 66);
}
crl_flag1=1;
}

else
{
crl_flag2=1;
if(crl_flag1==1)
{
crl_flag1=0;
OLED_Clear();
}
//显示“环境温度: C”
OLED_ShowChinese(1, 1, 8);
OLED_ShowChinese(1, 2, 9);
OLED_ShowChar(1, 5, ':');
OLED_ShowChar(1, 8, 'C');

//显示“环境湿度: %”
OLED_ShowChinese(1, 5, 10);
OLED_ShowChinese(1, 6, 9);
OLED_ShowChar(1, 13, ':');
OLED_ShowChar(1, 16, '%');

//显示“烟雾”
OLED_ShowChinese(2, 1, 44);
OLED_ShowChinese(2, 2, 45);
OLED_ShowChar(2, 5, ':');
OLED_ShowChar(2, 8, '%');

//显示“甲醛”
OLED_ShowChinese(2, 5, 53);
OLED_ShowChinese(2, 6, 54);
OLED_ShowChar(2, 13, ':');
OLED_ShowChar(2, 16, '%');

//显示”光照强度: Lux“
OLED_ShowChinese(3, 1, 15);
OLED_ShowChinese(3, 2, 16);
OLED_ShowChinese(3, 3, 28);
OLED_ShowChinese(3, 4, 29);
OLED_ShowChar(3, 9, ':');
OLED_ShowString(3, 14, "Lux");

//显示“二氧化碳: ”
OLED_ShowChinese(4, 1, 24);
OLED_ShowChinese(4, 2, 25);
OLED_ShowChinese(4, 3, 26);
OLED_ShowChinese(4, 4, 27);
OLED_ShowChar(4, 9, ':');
OLED_ShowString(4, 14, "ppm");
}

//if(huo==1) //发生火灾
//{
//OLED_ShowChinese(2, 5, 48);
//OLED_ShowChinese(2, 6, 49);
//OLED_ShowChinese(2, 7, 51);
//OLED_ShowChinese(2, 8, 52);
//}
//else
//{
//OLED_ShowString(2, 9, " ");
//OLED_ShowChinese(2, 6, 50);
//OLED_ShowChinese(2, 7, 51);
//OLED_ShowChinese(2, 8, 52);
//}
}

/**
* @brief 显示菜单1的传感器数据
* @param 无
* @retval 无
*/

void SensorDataDisplay1(void)
{

if(huo == 1||men==1)
{}
else
{
//显示环境温度数据
OLED_ShowNum(1, 6, sensorData.temp, 2);

//显示环境湿度数据
OLED_ShowNum(1, 14, sensorData.humi, 2);

//显示烟雾数据
OLED_ShowNum(2, 6, sensorData.MQ2, 2);

//显示甲醛数据
OLED_ShowNum(2, 14, sensorData.CH2O/20, 2);

//显示光照强度数据
OLED_ShowNum(3, 10, sensorData.lux, 4);

//显示CO2浓度数据
OLED_ShowNum(4, 10, sensorData.CO2, 4);
}
}
/**
* @brief 显示阈值设置界面1的固定内容
* @param 无
* @retval 无
*/

void OLED_settingsPage1(void)
{
if(count>4)
{
//显示“烟雾”
OLED_ShowChinese(1, 2, 44);
OLED_ShowChinese(1, 3, 45);
OLED_ShowChar(1, 7, ':');
//显示“甲醛”
OLED_ShowChinese(2, 2, 53);
OLED_ShowChinese(2, 3, 54);
OLED_ShowChar(2, 7, ':');
}
else
{
//显示“温度:”
OLED_ShowChinese(1, 2, 13);
OLED_ShowChinese(1, 3, 14);
OLED_ShowChinese(1, 4, 8);
OLED_ShowChinese(1, 5, 9);
OLED_ShowChar(1, 11, ':');

//显示“湿度:”
OLED_ShowChinese(2, 2, 13);
OLED_ShowChinese(2, 3, 14);
OLED_ShowChinese(2, 4, 10);
OLED_ShowChinese(2, 5, 9);
OLED_ShowChar(2, 11, ':');

//显示”光照强度:“
OLED_ShowChinese(3, 2, 15);
OLED_ShowChinese(3, 3, 16);
OLED_ShowChinese(3, 4, 28);
OLED_ShowChinese(3, 5, 29);
OLED_ShowChar(3, 11, ':');

//显示“二氧化碳:”
OLED_ShowChinese(4, 2, 24);
OLED_ShowChinese(4, 3, 25);
OLED_ShowChinese(4, 4, 26);
OLED_ShowChinese(4, 5, 27);
OLED_ShowChar(4, 11, ':');
}
}

/**
* @brief 显示阈值界面1的传感器数据
* @param 无
* @retval 无
*/

void settingsThresholdDisplay1(void)
{
if(count>4)
{
//显示烟雾阈值数据
OLED_ShowNum(1, 8, Sensorthreshold.MQ2Value, 2);

//显示甲醛阈值数据
OLED_ShowNum(2, 8, Sensorthreshold.CH2OValue, 2);
}
else
{
//显示环境温度阈值数据
OLED_ShowNum(1, 13, Sensorthreshold.tempValue, 2);

//显示环境湿度阈值数据
OLED_ShowNum(2, 13, Sensorthreshold.humiValue, 2);

//显示光照强度阈值数据
OLED_ShowNum(3, 13, Sensorthreshold.luxValue, 4);

//显示CO2浓度阈值数据
OLED_ShowNum(4, 13, Sensorthreshold.CO2Value, 4);
}
}
/**
* @brief 显示阈值界面的选择符号
* @param num 为显示的位置
* @retval 无
*/

void OLED_Option(uint8_t num)
{
switch(num)
{
case 1:
OLED_ShowChar(1,1,'>');
OLED_ShowChar(2,1,' ');
OLED_ShowChar(3,1,' ');
OLED_ShowChar(4,1,' ');
break;
case 2:
OLED_ShowChar(1,1,' ');
OLED_ShowChar(2,1,'>');
OLED_ShowChar(3,1,' ');
OLED_ShowChar(4,1,' ');
break;
case 3:
OLED_ShowChar(1,1,' ');
OLED_ShowChar(2,1,' ');
OLED_ShowChar(3,1,'>');
OLED_ShowChar(4,1,' ');
break;
case 4:
OLED_ShowChar(1,1,' ');
OLED_ShowChar(2,1,' ');
OLED_ShowChar(3,1,' ');
OLED_ShowChar(4,1,'>');
break;
case 5:
OLED_ShowChar(1,1,'>');
OLED_ShowChar(2,1,' ');
OLED_ShowChar(3,1,' ');
OLED_ShowChar(4,1,' ');
break;
case 6:
OLED_ShowChar(1,1,' ');
OLED_ShowChar(2,1,'>');
OLED_ShowChar(3,1,' ');
OLED_ShowChar(4,1,' ');
break;
default: break;
}
}

/**
* @brief 记录阈值界面下按KEY1的次数
* @param 无
* @retval 返回次数
*/

uint8_t SetSelection(void)
{
if(KeyNum == KEY_2)
{
KeyNum = 0;
count++;
if (count >= 7)
{
count=1;
}
if (count == 5)
{
OLED_Clear();//OLED清屏
}
}
return count;
}

/**
* @brief 对阈值界面的传感器阈值进行修改
* @param num 为当前用户需要更改的传感器阈值位置
* @retval 无
*/

void ThresholdModification(uint8_t num)
{
switch (num)
{
case 1:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.tempValue++;
if (Sensorthreshold.tempValue > 99)
{
Sensorthreshold.tempValue = 1;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
Sensorthreshold.tempValue;
if (Sensorthreshold.tempValue < 1)
{
Sensorthreshold.tempValue = 99;
}
}
break;
case 2:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.humiValue++;
if (Sensorthreshold.humiValue > 99)
{
Sensorthreshold.humiValue = 1;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
Sensorthreshold.humiValue;
if (Sensorthreshold.humiValue < 1)
{
Sensorthreshold.humiValue = 99;
}
}
break;
case 3:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.luxValue += 10;
if (Sensorthreshold.luxValue > 2000)
{
Sensorthreshold.luxValue = 0;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
Sensorthreshold.luxValue -= 10;
if (Sensorthreshold.luxValue > 2000)
{
Sensorthreshold.luxValue = 2000;
}
}
break;
case 4:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.CO2Value += 10;
if (Sensorthreshold.CO2Value > 2000)
{
Sensorthreshold.CO2Value = 0;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
Sensorthreshold.CO2Value -= 10;
if (Sensorthreshold.CO2Value > 2000)
{
Sensorthreshold.CO2Value = 2000;
}
}
break;
case 5:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.MQ2Value ++;
if (Sensorthreshold.MQ2Value > 99)
{
Sensorthreshold.MQ2Value = 99;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
if (Sensorthreshold.MQ2Value > 0)
{
Sensorthreshold.MQ2Value ;
}
}
break;
case 6:
if (KeyNum == 3)
{
KeyNum = 0;
Sensorthreshold.CH2OValue ++;
if (Sensorthreshold.CH2OValue > 99)
{
Sensorthreshold.CH2OValue = 99;
}
}
else if (KeyNum == 4)
{
KeyNum = 0;
if (Sensorthreshold.CH2OValue > 0)
{
Sensorthreshold.CH2OValue ;
}
}
break;
default: break;
}
}

/**
* @brief 获取二氧化碳数据
* @param *data 为数据传参
* @retval 无
*/

void CO2GetData(uint16_t *data,uint16_t *data1)
{
if (Usart3_RxFlag == 1)
{
Usart3_RxFlag = 0;
*data = (Usart3_RxPacket[2] * 256 + Usart3_RxPacket[3]);
*data1 = (Usart3_RxPacket[4] * 256 + Usart3_RxPacket[5]);
}
}

/**
* @brief 传感器数据扫描
* @param 无
* @retval 无
*/

void SensorScan(void)
{
DHT11_Read_Data(&sensorData.humi, &sensorData.temp);
LDR_LuxData(&sensorData.lux);
CO2GetData(&sensorData.CO2,&sensorData.CH2O); //获取二氧化碳和甲醛数据
YW_LuxData(&sensorData.MQ2);
}
void Flash_Readdata(void)//读取阈值参数
{
Sensorthreshold.CO2Value = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH
if(Sensorthreshold.CO2Value==65535||Sensorthreshold.CO2Value==0)
Sensorthreshold.CO2Value=2000;

Sensorthreshold.luxValue = FLASH_R(FLASH_START_ADDR+2);//从指定页的地址读FLASH
if(Sensorthreshold.luxValue==65535||Sensorthreshold.luxValue==0)
Sensorthreshold.luxValue=400;

Sensorthreshold.tempValue = FLASH_R(FLASH_START_ADDR+4);//从指定页的地址读FLASH
if(Sensorthreshold.tempValue==255||Sensorthreshold.tempValue==0)
Sensorthreshold.tempValue = 35;

Sensorthreshold.humiValue = FLASH_R(FLASH_START_ADDR+6);//从指定页的地址读FLASH
if(Sensorthreshold.humiValue==255||Sensorthreshold.humiValue==0)
Sensorthreshold.humiValue=75;

Sensorthreshold.MQ2Value = FLASH_R(FLASH_START_ADDR+8);//从指定页的地址读FLASH
if(Sensorthreshold.MQ2Value==255||Sensorthreshold.MQ2Value==0)
Sensorthreshold.MQ2Value=65;

Sensorthreshold.CH2OValue = FLASH_R(FLASH_START_ADDR+10);//从指定页的地址读FLASH
if(Sensorthreshold.CH2OValue==65535||Sensorthreshold.CH2OValue==0)
Sensorthreshold.CH2OValue=25;
}
void UsartSendReceiveData(void) //串口发送和接收数据,用于和手机APP通信
{
static uint8_t num=0;
unsigned char *dataPtr = NULL;
char *str1=0,i;
int setValue=0;
char setvalue[5]={0};
char SEND_BUF[200]; //发送数据缓存

dataPtr = ESP8266_GetIPD(0); //接收数据
if(dataPtr != NULL) //手机端下发了数据
{
Buzzer_ON();
Delay_ms(100);
Buzzer_OFF();
if(strstr((char *)dataPtr,"fengs:")!=NULL) //接收到设置温度上限的指令
{
SDflag=1;
num++;
num%=2;
if(num==1)
{
GPIO_SetBits(Relay_PROT, Relay1);
}
else
{
GPIO_ResetBits(Relay_PROT, Relay1);
}
}
if(strstr((char *)dataPtr,"Stop:")!=NULL) //接收到设置温度上限的指令
{
SDflag=0;
}
if(strstr((char *)dataPtr,"temp:")!=NULL) //接收到设置温度上限的指令
{
str1 = strstr((char *)dataPtr,"temp:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99)
{
Sensorthreshold.tempValue=setValue; //设置温度上限
}
}
if(strstr((char *)dataPtr,"humi:")!=NULL) //接收到设置湿度上限的指令
{
str1 = strstr((char *)dataPtr,"humi:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99)
{
Sensorthreshold.humiValue=setValue; //设置湿度上限
}
}
if(strstr((char *)dataPtr,"yanwu:")!=NULL) //接收到设置烟雾上限的指令
{
str1 = strstr((char *)dataPtr,"yanwu:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99)
{
Sensorthreshold.MQ2Value=setValue; //设置烟雾上限
}
}
if(strstr((char *)dataPtr,"CHValue:")!=NULL) //接收到设置甲醛上限的指令
{
str1 = strstr((char *)dataPtr,"CHValue:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99)
{
Sensorthreshold.CH2OValue=setValue; //设置甲醛上限
}
}
if(strstr((char *)dataPtr,"luxValue:")!=NULL) //接收到设置光照的指令
{
str1 = strstr((char *)dataPtr,"luxValue:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=9999)
{
Sensorthreshold.luxValue=setValue; //设置光照上限
}
}
if(strstr((char *)dataPtr,"COValue:")!=NULL) //接收到设置CO2的指令
{
str1 = strstr((char *)dataPtr,"COValue:");

while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字
{
str1 = str1 + 1;
Delay_ms(10);
}
i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字
{
setvalue[i] = *str1;
i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
Delay_ms(10);
}
setvalue[i] = '\\0'; //加上结尾符
setValue = atoi(setvalue);
if(setValue>=0 && setValue<=9999)
{
Sensorthreshold.CO2Value=setValue; //设置CO2上限
}
}
ESP8266_Clear();//清空缓存
}
if(sendFlag==1) //800ms上传一次数据
{
sendFlag = 0;
memset(SEND_BUF,0,sizeof(SEND_BUF)); //清空缓冲区

sprintf(SEND_BUF,"msg=#%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#",sensorData.temp,sensorData.humi,sensorData.CH2O/20,sensorData.lux,sensorData.CO2,sensorData.MQ2,beepflag1,beepflag2,beepflag3,beepflag4,beepflag5,beepflag6,huo==1?1:0,men==1?1:0);//发送的数据装载:温度,湿度,甲醛,PM2.5,co
ESP8266_SendData((u8 *)SEND_BUF, strlen(SEND_BUF)); //ESP8266模块发送数据到手机端
ESP8266_Clear(); //清除接收数据的缓存
}
}
int main(void)
{
menu =0;
ADCX_Init();
Timer2_Init(9,14398);//定时器2初始化
ESP8266_Init();//esp8266初始化
Uart3_Init();
huo_Init();//火焰传感器初始化
men_Init();//门磁传感器初始化
LDR_Init();//光敏电阻、烟雾传感器初始化
OLED_Init(); //OLED初始化
DHT11_Init();//温湿度初始化
LED_Init();//LED初始化
Buzzer_Init();//蜂鸣器初始化
Relay_Init();//继电器初始化
Key_Init();//按键初始化
OLED_ShowChinese(2, 3, 40);//欢迎使用
OLED_ShowChinese(2, 4, 41);
OLED_ShowChinese(2, 5, 42);
OLED_ShowChinese(2, 6, 43);
Delay_ms(1000);
OLED_Clear();//OLED清屏
Flash_Readdata();//读取阈值参数
GENERAL_TIM_Init();//定时器初始化
SensorScan();//获取传感器数据
menu=1;
while (1)
{
if(SDflag==0) SensorScan();//获取传感器数据
UsartSendReceiveData();
switch (menu)
{
case display_page1:
SensorDataDisplay1();//显示传感器1数据
OLED_Menu1();//显示主页面1固定信息
if(KeyNum == 1)
{
KeyNum = 0;
OLED_Clear_Flag = 1;
menu = 2;
}
if(shuaxing==1) //超出范围闪烁
{
shuaxing=0;
if (sensorData.temp > Sensorthreshold.tempValue)
{
OLED_ShowString(1,6," "); beepflag1=1;
}
else beepflag1=0;

if (sensorData.humi > Sensorthreshold.humiValue)
{
OLED_ShowString(1,14," ");beepflag2=1;
}
else beepflag2=0;

if (sensorData.MQ2 > Sensorthreshold.MQ2Value)
{
OLED_ShowString(2,6," "); beepflag3=1;
}
else beepflag3=0;

if (sensorData.lux < Sensorthreshold.luxValue)
{
OLED_ShowString(3,10," ");beepflag4=1;
}
else beepflag4=0;

if (sensorData.CO2 > Sensorthreshold.CO2Value)
{
OLED_ShowString(4,10," "); beepflag6=1;
}
else beepflag5=0;

if (sensorData.CH2O/20 > Sensorthreshold.CH2OValue)
{
OLED_ShowString(2,14," ");beepflag5=1;
}
else beepflag6=0;
}
break;
case settingsPage:
//从主页面跳转至设置页面时进行一次清屏
if (OLED_Clear_Flag)
{
OLED_Clear_Flag = 0;//清除清屏标志位
OLED_Clear();//清屏
}
ThresholdModification(SetSelection());//调节传感器阈值

settingsThresholdDisplay1();//显示传感器阈值1数据
OLED_settingsPage1();//显示阈值设置界面1固定信息
OLED_Option(SetSelection());//获取按键次数,从而判断“>”显示位置

if (KeyNum == KEY_1)//判断用户是否按下退出按键
{
KeyNum = 0;
OLED_Clear();//清屏
menu = display_page1;//回到主页面1
//存储修改的传感器阈值至flash内
FLASH_W(FLASH_START_ADDR, Sensorthreshold.CO2Value, Sensorthreshold.luxValue,
Sensorthreshold.tempValue, Sensorthreshold.humiValue,
Sensorthreshold.MQ2Value, Sensorthreshold.CH2OValue);
}
break;
default: break;
}
}
}

六、包含内容

在这里插入图片描述

七、资料分享

资料获取:请查看主页介绍搜索或观看开源视频获取

赞(0)
未经允许不得转载:171主机测评 » STM32项目开源:粮仓环境安防监测系统(代码 + 原理图 + 仿真)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址