STM32项目分享:基于STM32的智能家居系统

目录

一、前言

二、项目简介

三、原理图设计

四、PCB设计

五、程序设计

六、资料内容

七、资料获取


一、前言

项目成品图品:

哔哩哔哩视频链接:

【开源】基于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站一键三联关注私信博主即可获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值