目录1、仿真成品图2、功能介3、程序设计4、资料获取1、仿真成品图视频演示链接【Proteus仿真】STM32单片机智能家居环境监测_哔哩哔哩_bilibili2、功能介绍STM32单片机智能家居环境监测系统功能说明1.实时监测环境温湿度、烟雾浓度、光照强度、煤气浓度传感器数据2.OLED屏幕实时显示相关数据3.当温度高于阈值或烟雾浓度高于阈值或煤气高于阈值启动声光报警4.煤气浓度高于阈值打开通风5.按键可设置布防模式布防状态下红外光电监测到有人经过启动声光报警3、程序设计代码如下#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 stdio.h #include string.h #include stdarg.h #include stdlib.h #include stdlib.h #include stdbool.h #define KEY_1 1 #define KEY_2 2 #define KEY_3 3 #define KEY_4 4 #define FLASH_START_ADDR 0x0801f000 //写入的起始地址 SensorModules sensorData; //声明传感器数据结构体变量 SensorThresholdValue Sensorthreshold; //声明传感器阈值结构体变量 uint8_t menu 1; //显示菜单变量 uint8_t OLED_Clear_Flag; //阈值设置界面的清屏标志位 uint8_t start_Flag0; uint8_t sendFlag0; unsigned char SendString[30]; //向蓝牙发送的显示信息 uint8_t count 1; extern u8 shuaxing; extern vu16 USART1_RX_STA; 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 lt; 0) m 0; if (m gt; len) return NULL; if (n gt; len - m) n len - m; if (n gt; dst_size) n dst_size - 1; // 保留空间给null终止符 char *p src m; char *q dst; while (n-- gt; 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 gt; 0 amp;amp; *value_ptr lt; 9 amp;amp; i lt; sizeof(dest)-1) { dest[i] *value_ptr; } dest[i] \0; return (strlen(dest) gt; 0) ? atoi(dest) : 0; } void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len) { unsigned short count 0; for(; count lt; len; count) { USART_SendData(USARTx, *str); //发送数据 while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) RESET); //等待发送完成 } } /** brief 显示菜单1的固定内容 param 无 retval 无 */ void OLED_Menu1(void) { //显示“环境温度 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, %); //显示”光照强度 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(HW0) //有人 { OLED_ShowChinese(2, 7, 48); OLED_ShowChinese(2, 8, 50); } else //无人 { OLED_ShowString(2, 9, ); OLED_ShowChinese(2, 7, 49); OLED_ShowChinese(2, 8, 50); } } /** brief 显示菜单1的传感器数据 param 无 retval 无 */ void SensorDataDisplay1(void) { //显示环境温度数据 OLED_ShowNum(1, 6, sensorData.temp, 2); //显示环境湿度数据 OLED_ShowNum(1, 14, sensorData.humi, 2); //显示烟雾数据 OLED_ShowNum(2, 6, sensorData.MQ2, 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(count4) { //显示“烟雾” OLED_ShowChinese(1, 2, 44); OLED_ShowChinese(1, 3, 45); OLED_ShowChar(1, 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(count4) { //显示烟雾阈值数据 OLED_ShowNum(1, 8, Sensorthreshold.MQ2Value, 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 6) { count1; } if (count 5) { OLED_Clear(); //OLED清屏 } } return count; } /** brief 对阈值界面的传感器阈值进行修改 param num 为当前用户需要更改的传感器阈值位置 retval 无 */ void ThresholdModification(uint8_t num) { switch (num) { case 1: if (KeyNum KEY_3) { KeyNum 0; Sensorthreshold.tempValue; if (Sensorthreshold.tempValue 99) { Sensorthreshold.tempValue 1; } } else if (KeyNum KEY_4) { KeyNum 0; Sensorthreshold.tempValue--; if (Sensorthreshold.tempValue 1) { Sensorthreshold.tempValue 99; } } break; case 2: if (KeyNum KEY_3) { KeyNum 0; Sensorthreshold.humiValue; if (Sensorthreshold.humiValue 99) { Sensorthreshold.humiValue 1; } } else if (KeyNum KEY_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; default: break; } } /** brief 获取二氧化碳数据 param *data 为数据传参 retval 无 */ void CO2GetData(uint16_t *data) { //if (Usart3_RxFlag 1) { Usart3_RxFlag 0; *data (Usart3_RxPacket[2] * 256 Usart3_RxPacket[3]); } } /** brief 传感器数据扫描 param 无 retval 无 */ void SensorScan(void) { if(DHT11_ReadData())//温湿度采集 { sensorData.tempDHT11_GetTem(); sensorData.tempsensorData.temp/256; Delay_ms(10); sensorData.humiDHT11_GetHum(); sensorData.humisensorData.humi/256; } //DHT11_Read_Data(sensorData.humi, sensorData.temp); LDR_LuxData(sensorData.lux); //CO2GetData(sensorData.CO2); CO2_LuxData(sensorData.CO2); YW_LuxData(sensorData.MQ2); } void Flash_Readdata(void)//读取阈值参数 { Sensorthreshold.CO2Value1000; Sensorthreshold.luxValue600; Sensorthreshold.tempValue 35; Sensorthreshold.humiValue70; Sensorthreshold.MQ2Value65; } void EXTIx_Init(void)//按键外部中断 { NVIC_InitTypeDef NVIC_InitStructure; //NVIC寄存器结构体变量 EXTI_InitTypeDef EXTI_InitStructure; //外部中断相关寄存器结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能IO复用功能时钟 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0); // GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1); // GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource7); // GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6); // //配置外部中断4相关寄存器 EXTI_InitStructure.EXTI_Line EXTI_Line0|EXTI_Line1|EXTI_Line7|EXTI_Line6; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; EXTI_Init(EXTI_InitStructure); //中断通道使能 NVIC_InitStructure.NVIC_IRQChannel EXTI0_IRQn;//使能外部中断通道0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; //设置抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority 2;//设置响应优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel EXTI1_IRQn;//使能外部中断通道0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; //设置抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority 2;//设置响应优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel EXTI9_5_IRQn;//使能外部中断通道0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; //设置抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority 2;//设置响应优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); } void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line7) SET) { KeyNum3; EXTI_ClearITPendingBit(EXTI_Line7);//清除中断挂起标志位 } if(EXTI_GetITStatus(EXTI_Line6) SET) { KeyNum4; EXTI_ClearITPendingBit(EXTI_Line6);//清除中断挂起标志位 } } void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) SET) { KeyNum1; EXTI_ClearITPendingBit(EXTI_Line0);//清除中断挂起标志位 } } void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) SET) { KeyNum2; EXTI_ClearITPendingBit(EXTI_Line1);//清除中断挂起标志位 } } int main(void) { ADCX_Init(); Timer2_Init(9,14398);//定时器2初始化 // Uart2_Init(9600); // Uart3_Init(); huo_Init();//火焰传感器初始化 LDR_Init();//光敏电阻、烟雾传感器初始化 OLED_Init(); //OLED初始化 DHT11_Init();//温湿度初始化 Buzzer_Init();//蜂鸣器初始化 Relay_Init();//继电器初始化 EXTIx_Init();//按键外部中断初始化 OLED_ShowChinese(2, 3, 40);//欢迎使用 OLED_ShowChinese(2, 4, 41); OLED_ShowChinese(2, 5, 42); OLED_ShowChinese(2, 6, 43); Delay_ms(2000); OLED_Clear(); //OLED清屏 Flash_Readdata();//读取阈值参数 GENERAL_TIM_Init();//定时器初始化 menu1; while (1) { SensorScan(); //获取传感器数据 switch (menu) { case display_page1: SensorDataDisplay1(); //显示传感器1数据 OLED_Menu1(); //显示主页面1固定信息 if(KeyNum 1) { KeyNum 0; OLED_Clear_Flag 1; menu 2; } if(KeyNum 2) //开启布防 { KeyNum 0; start_Flag 1; OLED_Clear(); OLED_ShowChinese(2, 3, 51); OLED_ShowChinese(2, 4, 52); OLED_ShowChinese(2, 5, 55); OLED_ShowChinese(2, 6, 56); Delay_ms(500); OLED_Clear(); } if(KeyNum 3) //关闭布防 { KeyNum 0; start_Flag 0; OLED_Clear(); OLED_ShowChinese(2, 3, 53); OLED_ShowChinese(2, 4, 54); OLED_ShowChinese(2, 5, 55); OLED_ShowChinese(2, 6, 56); Delay_ms(500); OLED_Clear(); } //if(shuaxing1) { shuaxing0; if (sensorData.temp gt; Sensorthreshold.tempValue) { OLED_ShowString(1,6, ); } if (sensorData.humi gt; Sensorthreshold.humiValue) { OLED_ShowString(1,14, ); } if (sensorData.MQ2 gt; Sensorthreshold.MQ2Value) { OLED_ShowString(2,6, ); } if (sensorData.lux lt; Sensorthreshold.luxValue) { OLED_ShowString(3,10, ); } if (sensorData.CO2 gt; Sensorthreshold.CO2Value) { OLED_ShowString(4,10, ); } } break; case settingsPage: //从主页面跳转至设置页面时进行一次清屏 if (OLED_Clear_Flag) { OLED_Clear_Flag 0; //清除清屏标志位 OLED_Clear(); //清屏 } ThresholdModification(SetSelection()); //调节传感器阈值 settingsThresholdDisplay1(); //显示传感器阈值1数据 OLED_settingsPage1(); //显示阈值设置界面1固定信息 OLED_Option(SetSelection()); //获取按键次数从而判断“gt;”显示位置 if (KeyNum KEY_1) //判断用户是否按下退出按键 { KeyNum 0; OLED_Clear(); //清屏 menu display_page1; //回到主页面1 } break; default: break; } } }4、资料获取资料获取请查看主页或者观看视频演示链接获取资料获取
