目录
一、前言
项目成品图品:

哔哩哔哩视频链接:
【开源】基于STM32的智能家居系统
二、项目简介
1、主要器件
主控:STM32F103C8T6(最小系统版本)
模块: 826601s + 步进电机(28) + LED(蓝色) + LED(黄色) + SG90舵机+K210+温湿度DHT11+MQ135+火焰传感器+蜂鸣器LED(红色)+MQ4 + ESP32CAM + OLED(0.96) 显示数据 + 按键界面切换 * 4 + 语音控制SU30T
2、功能详解
1、STM32循环读取所有传感器(DHT11, MQ135, MQ4)的数据。 在OLED上更新显示当前选定的界面数据。
2、检测按键操作,执行界面切换或其他功能。
3、环境异常:当任何传感器值超过阈值(如检测到火焰、CO浓度过高),STM32会:点亮红色LED,启动蜂鸣器报警。
4、通过ESP8266向手机App或云平台发送报警信息。
5、语音控制:SU-03T接收到特定指令后,通过串口通知STM32,STM32执行相应动作(如控制舵机转动、LED、步进电机)。
6、视觉识别:K210完成识别后,将结果(如“识别到人脸”)发送给STM32,STM32根据结果决定下一步动作(如舵机转动跟踪、蜂鸣器响一声)。
7、远程指令(APP):STM32通过ESP8266接收云端指令,控制电机、LED等设备。
三、原理图设计

四、PCB设计
PCB图

3D图

五、程序设计
#include "delay.h"
#include "sys.h"
#include "led.h" //控制器
#include "oled.h"
#include "esp8266.h"
#include "Timer.h"
#include "Key.h"
#include "stmflash.h"
#include "su_03t.h"
// 传感/执行模块
#include "dht11.h"
#include "adc.h"
#include "../HARDWARE/Step_motor/MOTOR.h"
#include "../HARDWARE/Fire Sensor/Fire.h"
//C库
#include <string.h>
#include "stdio.h"
#include "math.h"
#include "stdbool.h"
#include "pwm.h" // 舵机控制
#include "Usart.h" // 串口通信
/*********************************** 变量声明**********************************/
extern unsigned char esp8266_buf[buf_len];
// 定义在头文件中声明的外部变量
control_mode MODE = manual_mode; // 初始化为手动模式
//阈值结构体
struct Set_data
{
u16 temp_H; //温度上限
u16 temp_L; //温度下限
u16 air_H; //空气质量上限
u16 co_H; //一氧化碳上限
};
struct Set_data Out_data={30,20,30,40};//初始化阈值
//数据获取
u16 temp_value=0;
u16 humi_value=0;
u16 co_value=0;
float air_value=0;
DHT11_Data_TypeDef DHT11_Data;//dht11添加变量
////按键相关的变量
u8 key_num=0,Page_flag=1;
char TIMER_IT=0,WiFiInit_time,Flagout=1;
//oled相关变量
u8 oled_Fill_flag=1;//OLED清屏标志
char oled_str[100];//OLED显示缓存
char date[200];//esp8266发送缓存
bool beep_flag=false;//蜂鸣器标志位
//DOOR=false;//门锁状态
u8 alarm_flag=0;//报警标志位
u8 air_alarm;
u8 co_alarm;
u8 face_state;//人脸状态 是否成功识别
u16 face_num; //识别次数
u8 success_sent;
uint16_t fire_val;
bool has_fire; // 若传感器为高电平触发
u8 fire_flag=0;//火灾播报标志位
u8 co_flag=0;
u8 air_flag=0;
int num;
/********************************函数声明**********************************/
// 在main函数前添加函数声明
void Page_data(void); // 数据显示界面
void Page_control(void); //控制外设
void Page_setting(void); // 设置界面
void APP_Control(void); //APP数据下发
void BI_BI(void); //哔哔提醒数据下发
int main(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Adc_Init();//可燃气 空气质量
DHT11_Init();//初始化DHT11
LED_Init();
Servo_Init(); // 初始化舵机
Serial_Iint(9600); // 初始化串口3用于K210通信
COLD=OFF;//制冷关闭
HOT=OFF;//制热关闭
LED=OFF;//LED关闭
BEEP=OFF;//蜂鸣器关闭
DOOR=OFF;//关门
Key_Init();//按键初始化
SU_03T_Iint(9600);//SU03T 语言
motor_init(); // 步进电机初始化
FIRE_Init(); // 火焰传感器初始化
SU_03T_Iint(9600);//语音模块
OLED_Init();//OLED初始化
OLED_Clear(0);
do
{
OLED_ShowText(0, 0,(u8*) "是否需要联网?", 0);
OLED_ShowText(8, 4,(u8*) "1.是 2.否", 0);
key_num=KEY_Scan(0);//按键扫描
if(key_num==1)//需要联网
{
OLED_Clear(0);
Timer_Init();
ESP8266_Init(115200);
break;
}
}while(key_num!=2);
OLED_Clear(0);
/*读出内存数据*/
STMFLASH_Read(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+4, &Out_data.air_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+6, &Out_data.co_H,1);
delay_ms(100);
while(1)
{
/*********************************数据处理区*********************************/
//获取温湿度
Read_DHT11(&DHT11_Data);
temp_value= DHT11_Data.temp_int; //获取温度
humi_value= DHT11_Data.humi_int; //获取湿度
//获取一氧化碳
co_value= GetMQ4Value();
//获取空气质量
air_value=MQ135_GetData_PPM();
/***************判断是否有火**************************/
fire_val = FIRE_GetData();
has_fire = (fire_val == 1); // 若传感器为低电平触发
/*******************向巴法云发送数据***************************************/
if(TIMER_IT)
{
TIMER_IT=0;
sprintf(date,"cmd=2&uid=%s&topic=data&msg=#%d#%d#%d#%d#%d#%d#%d#%d#sensordata#\r\n",\
BEMFA_ID,
MODE,(int)temp_value,(int)humi_value,(int)air_value,(int)co_value,(int)co_alarm,(int)air_alarm,(int)fire_val);
ESP8266_SendData((unsigned char *)date);//ESP8266发送数据
}
/*********************************人机交互区**************************************************/
key_num=KEY_Scan(0);//按键扫描
if(key_num==1)//界面切换键
{
Page_flag++;
Page_flag=Page_flag%3;
OLED_Clear(0);//清屏
}
//界面切换功能
switch(Page_flag)
{
case 1:
Page_data(); // 第一界面 - 数据显示
break;
case 2:
Page_control(); //控制外设; // 第三界面 - 设置界面
break;
case 0:
Page_setting(); // 第三界面 - 设置界面
break;
}
/*********************************模式控制区*********************************/
/******************APP指令下发********************************/
APP_Control();//阈值下发 模式转换
/********************自动模式******************************/
/*当环境温度过高打开空调制冷,
当环境温度过低打开空调制热,
*/
if(MODE==auto_mode){
//温度控制
if(temp_value>Out_data.temp_H)
{
COLD=ON;
HOT=OFF;
}
else if(temp_value<Out_data.temp_L)
{
COLD=OFF;
HOT=ON;
}
else
{
COLD=OFF;
HOT=OFF;
}
// 火焰传感器联动蜂鸣器:有火则鸣叫,无火则静音
if(fire_val==1){
beep_flag=true;
if(fire_flag==1){
SU_03T_SendArray(fire_TxPacket, 5);
fire_flag=0;
}
}else{ beep_flag = false;}
// 空气质量超标控制
if(air_value > Out_data.air_H)
{
air_alarm=1;
// 空气质量差时开启窗帘通风
if(StateCurtain == 0) // 窗帘关闭状态
{
Motor_Ctrl_Angle_Z(90, MOTOR_SPEED); // 打开窗帘
StateCurtain = 1;
}
// 开启制冷改善空气质量
COLD = ON;
if(air_flag==1){
SU_03T_SendArray(air_TxPacket, 5);
air_flag=0;
}
}
else { air_alarm=0;}
// CO浓度超标控制
if(co_value > Out_data.co_H)
{
co_alarm=1;
// CO超标时开启窗帘通风
// if(StateCurtain == 0) // 窗帘关闭状态
// {
// Motor_Ctrl_Angle_Z(90, MOTOR_SPEED); // 打开窗帘
// StateCurtain = 1;
// }
// // 开启制冷降低室内温度
// COLD = ON;
// 触发报警
beep_flag = true;
if(co_flag==1){
SU_03T_SendArray(co_TxPacket, 5);
co_flag=0;
}
}else{co_alarm=0;}
if (Serial_RxFlag == 1)
{
success_sent = 1;
Serial_RxFlag = 0;
if (strcmp(Serial_RxPacket, "success") == 0)
{
if(!DOOR) {Servo_SetAngle(90); DOOR=ON;
SU_03T_SendArray(success_TxPacket, 5);
face_state=1;
face_num+=1;} // 舵机转到90度位置开门
}
else if (strcmp(Serial_RxPacket, "Err") == 0)
{
static int err_count = 0;
// static int error_sent = 0;
if(DOOR){Servo_SetAngle(0); DOOR=OFF;
face_state=0;
face_num+=1;} // 舵机转回0度位置关门
err_count++;
if (err_count >= 20) {
SU_03T_SendArray(nosuccess_TxPacket, 5);
// error_sent++;
BEEP = ON; // 报警提示
delay_ms(500);
BEEP = OFF;
delay_ms(500);
BEEP = ON;
delay_ms(500);
BEEP = OFF; // 连续报警三声
delay_ms(500);
BEEP = ON;
delay_ms(500);
BEEP = OFF;
err_count = 0; // 复位计数
}
}
memset(Serial_RxPacket, 0, 50);
static u16 last_sent_face_num = 0;
if(face_num != last_sent_face_num && success_sent == 1) {
sprintf(date,"cmd=2&uid=%s&topic=data&msg=#%d#%d#costdata#\r\n",\
BEMFA_ID, face_state,face_num);
ESP8266_SendData((unsigned char *)date);//ESP8266发送数据
last_sent_face_num = face_num;
success_sent = 0;
}
}
}//自动模式
/********************手动模式*****************************/
if(MODE==manual_mode)//手动模式
{
// 检查是否需要发送空气质量
if(SU_03T_GetSendAirFlag==1)
{
// 发送帧头
SU_03T_SendByte(0xAA);
SU_03T_SendByte(0x55);
// 发送命令字
SU_03T_SendByte(0x06);
// 发送年月日时分秒数据
int air_data[1];
air_data[0] = (int)air_value; //空气质量
// 调整发送顺序为低字节在后
// 发送每个时间值(4字节)
for(int i = 0; i < 1; i++)
{
// 调整发送顺序为低字节在后
SU_03T_SendByte(air_data[i] & 0xFF); // 最低字节
SU_03T_SendByte((air_data[i] >> 8) & 0xFF); // 次低字节
SU_03T_SendByte((air_data[i] >> 16) & 0xFF); // 次高字节
SU_03T_SendByte((air_data[i] >> 24) & 0xFF); // 最高字节
}
// 发送帧尾
SU_03T_SendByte(0x55);
SU_03T_SendByte(0xAA);
SU_03T_GetSendAirFlag=0; //重置标志位
}
/****************APP控制***************************/
//LED控制
if(strstr((const char *)esp8266_buf,"LED_ON")!=0)
{
LED=ON;
BI_BI();//哔哔提醒
}
else if(strstr((const char *)esp8266_buf,"LED_OFF")!=0)
{
LED=OFF;
BI_BI();//哔哔提醒
}
//制冷控制
if(strstr((const char *)esp8266_buf,"COLD_ON")!=0)
{
COLD=ON;
BI_BI();//哔哔提醒
}
else if(strstr((const char *)esp8266_buf,"COLD_OFF")!=0)
{
COLD=OFF;
BI_BI();//哔哔提醒
}
//制热控制
if(strstr((const char *)esp8266_buf,"HOT_ON")!=0)
{
HOT=ON;
BI_BI();//哔哔提醒
}
else if(strstr((const char *)esp8266_buf,"HOT_OFF")!=0)
{
HOT=OFF;
BI_BI();//哔哔提醒
}
// 手动模式下的窗帘控制
if( strstr((const char *)esp8266_buf,"CT_ON")!=0 ) // 窗帘打开
{
BI_BI();//哔哔提醒
if(StateCurtain == 0)
{
Motor_Ctrl_Angle_Z(90, MOTOR_SPEED);
StateCurtain = 1;
}
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if( strstr((const char *)esp8266_buf,"CT_OFF")!=0 ) // 窗帘关闭
{
BI_BI();//哔哔提醒
if(StateCurtain == 1)
{
Motor_Ctrl_Angle_F(90, MOTOR_SPEED);
StateCurtain = 0;
}
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
//制热控制
if(strstr((const char *)esp8266_buf,"DOOR_ON")!=0)
{
if(!DOOR){Servo_SetAngle(90); DOOR=ON;}
BI_BI();//哔哔提醒
}
else if(strstr((const char *)esp8266_buf,"DOOR_OFF")!=0)
{
if(DOOR){Servo_SetAngle(0); DOOR=OFF;}
BI_BI();//哔哔提醒
}
ESP8266_Clear();//清除缓存
}//手动模式
}//while
}//main
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
if(num>=5){
fire_flag=1;//火灾播报标志位
co_flag=1;
air_flag=1;
num=0;
}
num++;
TIMER_IT=1;
if(beep_flag)
{
BEEP=!BEEP;
}
else
{
BEEP=0;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void APP_Control(void)
{
//模式切换
if( strstr((const char *)esp8266_buf,"ZD")!=0 )
{
MODE=auto_mode;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if( strstr((const char *)esp8266_buf,"SD")!=0 )
{
MODE=manual_mode;
beep_flag=false;
BEEP=OFF;
HOT=OFF;
COLD=OFF;
LED=OFF;
if(DOOR){Servo_SetAngle(0); DOOR=OFF;}
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
char *jj_ptr = strstr((char *)esp8266_buf, "TH");
if (jj_ptr != NULL && sscanf(jj_ptr + 2, "=%hu", &Out_data.temp_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H, 1);
}
char *tw_ptr = strstr((char *)esp8266_buf, "TL");
if (tw_ptr != NULL && sscanf(tw_ptr + 2, "=%hu", &Out_data.temp_L) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L, 1);
}
// CO阈值设置
char *co_ptr = strstr((char *)esp8266_buf, "COH");
if (co_ptr != NULL && sscanf(co_ptr + 3, "=%hu", &Out_data.co_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.co_H, 1);
}
// 空气质量阈值设置
char *air_ptr = strstr((char *)esp8266_buf, "AIR");
if (air_ptr != NULL && sscanf(air_ptr + 3, "=%hu", &Out_data.air_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.air_H, 1);
}
}
// 数据显示界面
void Page_data(void)
{
// 添加按键2的模式切换功能
if(key_num==2)//模式切换键
{
MODE++;
if(MODE > manual_mode) MODE = auto_mode; // 循环切换:自动->手动->自动
// 切换到手动模式时关闭报警和设备
if(MODE == manual_mode)
{
beep_flag=false;
BEEP=OFF;
HOT=OFF;
COLD=OFF;
LED=OFF;
if(DOOR){Servo_SetAngle(0); DOOR=OFF;}
if(StateCurtain == 1)
{
Motor_Ctrl_Angle_F(90, MOTOR_SPEED);
StateCurtain = 0;
}
}
}
//空气质量
sprintf(oled_str,"空气质量:%dppm ",(int)air_value);
OLED_ShowText(0,0,(u8*)oled_str,0);
//一氧化碳浓度
sprintf(oled_str,"CO浓度:%dppm ",(int)co_value);
OLED_ShowText(0,2,(u8*)oled_str,0);
//温度显示
sprintf(oled_str,"温度:%3d℃ ",(int)temp_value);
OLED_ShowText(0,4,(u8*)oled_str,0);
//湿度显示
sprintf(oled_str,"湿度:%3d%%",(int)humi_value);
OLED_ShowText(0,6,(u8*)oled_str,0);
//模式状态
sprintf(oled_str,"%s",MODE?"手动":"自动");
OLED_ShowText(95,6,(u8*)oled_str,0);
}
//控制界面
void Page_control(void)
{
static u8 Index_flag=1;
static u8 is_curtain_page=0; // 0为第一页,1为窗帘页
// 显示界面内容
if(is_curtain_page == 0) // 第一页:LED、制冷、制热、门锁
{
sprintf(oled_str,"LED:%s",LED?"ON ":"OFF");
OLED_ShowText(16,0,(u8 *)oled_str,0);
sprintf(oled_str,"制冷:%s",COLD?"ON ":"OFF");
OLED_ShowText(16,2,(u8 *)oled_str,0);
sprintf(oled_str,"制热:%s",HOT?"ON ":"OFF");
OLED_ShowText(16,4,(u8 *)oled_str,0);
sprintf(oled_str,"门锁:%s",DOOR?"ON ":"OFF");
OLED_ShowText(16,6,(u8 *)oled_str,0);
// 处理按键2选择逻辑
if(key_num==2)
{
Index_flag++;
if(Index_flag > 4) // 当选择超过门锁时,进入窗帘页面
{
is_curtain_page = 1;
Index_flag = 1; // 重置为窗帘选择
OLED_Clear(0);
}
}
// 箭头显示和控制逻辑
switch(Index_flag)
{
case 1:
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 2:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)">",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 3:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)">",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 4:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)">",16) ;
break;
}
if(MODE==manual_mode)//手动模式下
{
if(Index_flag==1&&key_num==3) LED=ON;
if(Index_flag==1&&key_num==4) LED=OFF;
if(Index_flag==2&&key_num==3) COLD=ON;
if(Index_flag==2&&key_num==4) COLD=OFF;
if(Index_flag==3&&key_num==3) HOT=ON;
if(Index_flag==3&&key_num==4) HOT=OFF;
// 门锁控制
if(Index_flag==4&&key_num==3) if(!DOOR) {Servo_SetAngle(90); DOOR=ON;}
if(Index_flag==4&&key_num==4) if(DOOR){Servo_SetAngle(0); DOOR=OFF;}
}
}
else // 窗帘控制页面
{
sprintf(oled_str,"窗帘:%s",StateCurtain ? "ON ":"OFF");
OLED_ShowText(16,0,(u8 *)oled_str,0);
// 处理按键2返回第一页
if(key_num==2)
{
is_curtain_page = 0;
Index_flag = 1; // 返回LED选择
OLED_Clear(0);
}
// 箭头显示
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
if(MODE==manual_mode)//手动模式下
{
// 窗帘控制
if(key_num==3 && StateCurtain==0) // 开启窗帘
{
Motor_Ctrl_Angle_Z(90, MOTOR_SPEED);
StateCurtain = 1;
BI_BI(); // 提示音
}
if(key_num==4 && StateCurtain==1) // 关闭窗帘
{
Motor_Ctrl_Angle_F(90, MOTOR_SPEED);
StateCurtain = 0;
BI_BI(); // 提示音
}
}
}
}
// 设置界面
void Page_setting(void)
{
static u8 Index_flag=1;
// 显示设置参数
sprintf(oled_str,"温度上限:%d ",Out_data.temp_H);
OLED_ShowText(16,0,(u8 *)oled_str,0);
sprintf(oled_str,"温度下限:%d ",Out_data.temp_L);
OLED_ShowText(16,2,(u8 *)oled_str,0);
sprintf(oled_str,"CO阈值:%d ",Out_data.co_H);
OLED_ShowText(16,4,(u8 *)oled_str,0);
sprintf(oled_str,"空气质量:%d ",Out_data.air_H);
OLED_ShowText(16,6,(u8 *)oled_str,0);
// 处理参数调节逻辑
if(key_num==2)
{
Index_flag++;
Index_flag=Index_flag%4; // 修改为4个选项
}
// 箭头显示和参数调节逻辑
switch(Index_flag)
{
case 1:
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 2:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)">",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 3:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)">",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 0:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)">",16) ;
break;
}
// 处理参数调节
//温度上限
if(Index_flag==1&&key_num==3)
{
Out_data.temp_H < 100 ? Out_data.temp_H++ : 100;//温度上限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
}
if(Index_flag==1&&key_num==4)
{
Out_data.temp_H > 0 ? Out_data.temp_H-- : 0; //温度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
}
//温度下限
if(Index_flag==2&&key_num==3)
{
Out_data.temp_L < 100 ? Out_data.temp_L++ : 100;//温度下限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
}
if(Index_flag==2&&key_num==4)
{
Out_data.temp_L > 0 ? Out_data.temp_L-- : 0; //温度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
}
//CO阈值
if(Index_flag==3&&key_num==3)
{
Out_data.co_H < 200 ? Out_data.co_H++ : 200;//CO阈值不能超过200ppm
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.co_H,1);
}
if(Index_flag==3&&key_num==4)
{
Out_data.co_H > 0 ? Out_data.co_H-- : 0; //CO阈值不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.co_H,1);
}
//空气质量阈值
if(Index_flag==0&&key_num==3)
{
Out_data.air_H < 100 ? Out_data.air_H++ : 100;//空气质量阈值不能超过100ppm
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.air_H,1);
}
if(Index_flag==0&&key_num==4)
{
Out_data.air_H > 0 ? Out_data.air_H-- : 0; //空气质量阈值不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.air_H,1);
}
}
void BI_BI(void){
BEEP=ON;
delay_ms(150);
BEEP=OFF;
}
六、资料内容

七、资料获取
B站一键三联关注私信博主即可获取
1071

被折叠的 条评论
为什么被折叠?



