STM32厨房安全检测(蓝牙版)

一、前言

项目成品图片:

哔哩哔哩视频链接:

【STM32厨房安全检测(蓝牙版)】 https://www.bilibili.com/video/BV1gHdUBZEkJ/?share_source=copy_web&vd_source=097fdeaf6b6ecfed8a9ff7119c32faf2

(资料分享见文末)

二、项目简介

1.功能详解

基于STM32厨房安全检测(蓝牙版)

功能如下:

  1. STM32F103C8T6单片机作为主控芯片
  2. 检测功能:检测环境温湿度、烟雾浓度、一氧化碳、火焰信号和人体信号
  3. 显示功能:OLED显示环境参数
  4. 手动控制:手动模式下可通过按键控制水泵、风扇、LED灯和阀门(舵机模拟)的开关
  5. 自动模式:自动模式下系统检测到有人时开启LED,温度高于阈值开启风扇和蜂鸣器报警,烟雾和一氧化碳超过阈值开启风扇关闭阀门并开启蜂鸣器报警,发生火灾时关闭阀门开启水泵和蜂鸣器报警
  6. 模式切换:通过按键可切换自动模式或手动模式
  7. 阈值调节:按键可调节各参数的阈值
  8. 蓝牙APP:通过蓝牙连接手机APP,可查看环境信息数据与控制指令下发

2.主要器件

  • STM32F103C8T6单片机
  • OLED 屏幕
  • DHT11温湿度传感器
  • MQ2烟雾传感器
  • MQ7一氧化碳传感器
  • 火焰传感器
  • 光电红外传感器
  • BT04-A蓝牙模块
  • 继电器
  • 有源蜂鸣器
  • 水泵
  • 风扇模块
  • 舵机

三、原理图设计

四、PCB硬件设计

PCB图

五、程序设计

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "servo.h"
#include "oled.h"
#include "dht11.h"
#include "led.h"
#include "key.h"
#include "tim2.h"   
#include "tim3.h"     
#include "Modules.h"
#include "flash.h"
#include "HW.h"
#include "servo.h"
#include "usart2.h"
#include "usart.h"
#include "beep.h"
#include "fan.h"
#include "bump.h"


/****************异方辰电子工作室******************
					    STM32
											
 * 项目			:	STM32智能厨房安全系统(蓝牙版)                  
 * 版本			:   V3.0
 * 日期			:   2026.4.18
 * MCU			:	STM32F103C8T6
 * 接口			:	见代码		
 * IP账号		:	异方辰电子/辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
 * 作者			:	辰哥 
 * 工作室		:   异方辰电子工作室
 * 授权IP	 	:	辰哥单片机设计、异方辰电子、YFC电子、异方辰系列 
 * 官方网站	    :	www.yfcdz.cn	

**********************BEGIN***********************/

#define KEY_Long1	11
#define FLASH_START_ADDR  0x0800FC00//写入的起始地址

SensorModules sensorData;	//声明传感器数据结构体变量
SensorThresholdValue Sensorthreshold;	//声明传感器阈值结构体变量
DriveModules driveData;		
uint8_t menu = 1;	//显示菜单变量
uint8_t mode = 1;	//系统模式  1自动  2手动  3设置

//系统静态变量
uint8_t count_a = 1;  //自动模式按键数
uint8_t count_m = 1;  //手动模式按键数
uint8_t count_s = 1;	 //设置模式按键数

/**
  * @brief  显示菜单内容
  * @param  无
  * @retval 无
  */
enum 
{
	AUTO_MODE = 1,
	MANUAL_MODE,
	SETTINGS_MODE
	
}MODE_PAGES;


/**
  * @brief  显示菜单1的固定内容
  * @param  无
  * @retval 无
  */
void OLED_autoPage1(void)
{
	//显示"温度:  C"
	OLED_ShowChinese(0, 0, 0,16,1);
	OLED_ShowChinese(16, 0, 2,16,1);
	OLED_ShowChar(32, 0, ':',16,1);
	
	//显示"湿度:   %"
	OLED_ShowChinese(64, 0, 1,16,1);
	OLED_ShowChinese(80,0, 2,16,1);
	OLED_ShowChar(96,0, ':',16,1);
	
	//显示"烟雾浓度: "
	OLED_ShowChinese(0, 16, 10,16,1);
	OLED_ShowChinese(16,16, 11,16,1);
	OLED_ShowChinese(32,16, 12,16,1);
	OLED_ShowChinese(48,16, 2,16,1);
	OLED_ShowChar(64,16, ':',16,1);

	
	//显示"一氧化碳: "
	OLED_ShowChinese(0, 32, 18,16,1);
	OLED_ShowChinese(16,32, 19,16,1);
	OLED_ShowChinese(32,32, 20,16,1);
	OLED_ShowChinese(48,32, 21,16,1);
	OLED_ShowChar(64,32, ':',16,1);

	
	//显示"系统模式:"
	OLED_ShowChinese(0,48,50,16,1);
	OLED_ShowChinese(16,48,51,16,1);
	OLED_ShowChinese(32,48,52,16,1);
	OLED_ShowChinese(48,48,53,16,1);	
	OLED_ShowChar(64,48, ':',16,1);
}

/**
  * @brief  显示菜单2的固定内容
  * @param  无
  * @retval 无
  */
void OLED_autoPage2(void) 
{
	//显示"火焰:"
	OLED_ShowChinese(0 ,0,54,16,1);
	OLED_ShowChinese(16,0,55,16,1);
	OLED_ShowChinese(32,0,56,16,1);
	OLED_ShowChinese(48,0,57,16,1);
	OLED_ShowChar(64,0,':',16,1);
	
	//显示"人体"
	OLED_ShowChinese(0 ,16,58,16,1);
	OLED_ShowChinese(16,16,59,16,1);
	OLED_ShowChinese(32,16,56,16,1);
	OLED_ShowChinese(48,16,57,16,1);
	OLED_ShowChar(64,16,':',16,1);
	
	
}

/**
  * @brief  显示菜单1的传感器数据
  * @param  无
  * @retval 无
  */
void SensorDataDisplay1(void)
{
    char all_data[200];  // 字符串变长,适当扩大缓冲区

    // 格式化所有数据,添加火焰和人体状态
    sprintf(all_data, 
        "温度: %d\r\n"
        "湿度: %d\r\n"
        "烟雾浓度: %d\r\n"
        "燃气浓度: %d\r\n"
        "火焰: %s\r\n"
        "人体: %s\r\n",
        sensorData.temp,
        sensorData.humi,
        sensorData.smog,
        sensorData.CO,
        sensorData.fire ? "有火" : "无火",
        sensorData.HW ? "有人" : "无人"
    );

    USART2_SendString(all_data);
    delay_ms(100);
	
	//显示温度数据
	OLED_ShowNum(40,0 , sensorData.temp, 2,16,1);
	//显示湿度数据
	OLED_ShowNum(104, 0, sensorData.humi, 2,16,1);
	
	//显示烟雾浓度数据
	OLED_ShowNum(72, 16, sensorData.smog, 4,16,1);
	
	//显示甲烷浓度数据
	OLED_ShowNum(72, 32, sensorData.CO, 4,16,1);
	
	//显示系统状态数据
if (mode == MANUAL_MODE)
	{
		OLED_ShowChinese(72, 48, 15,16,1);//手动
		OLED_ShowChinese(88, 48, 17,16,1);		
	}
	else
	{
		OLED_ShowChinese(72, 48, 16,16,1);//自动
		OLED_ShowChinese(88, 48, 17,16,1);			
	}
	
	
}

/**
  * @brief  显示菜单2的传感器数据
  * @param  无
  * @retval 无
  */
void SensorDataDisplay2(void)
{
	    char all_data[200];  // 字符串变长,适当扩大缓冲区

    // 格式化所有数据,添加火焰和人体状态
    sprintf(all_data, 
        "温度: %d\r\n"
        "湿度: %d\r\n"
        "烟雾浓度: %d\r\n"
        "燃气浓度: %d\r\n"
        "火焰: %s\r\n"
        "人体: %s\r\n",
        sensorData.temp,
        sensorData.humi,
        sensorData.smog,
        sensorData.CO,
        sensorData.fire ? "有火" : "无火",
        sensorData.HW ? "有人" : "无人"
    );

    USART2_SendString(all_data);
    delay_ms(100);
	
	if (!sensorData.fire)
	{
		OLED_ShowChinese(72, 0, 61,16,1);
		OLED_ShowChinese(88, 0, 54,16,1);		
	}
	else
	{
		OLED_ShowChinese(72, 0, 60,16,1);//有火
		OLED_ShowChinese(88, 0, 54,16,1);	
	}
	
	if (!sensorData.HW)
	{
		OLED_ShowChinese(72, 16, 61,16,1);
		OLED_ShowChinese(88, 16, 58,16,1);	
	}
	else
	{

		OLED_ShowChinese(72, 16, 60,16,1);//有人
		OLED_ShowChinese(88, 16, 58,16,1);		
		
	}	
	

}

/**
  * @brief  显示阈值设置界面1的固定内容
  * @param  无
  * @retval 无
  */
void OLED_settingsPage1(void)
{
	//显示"温度阈值:"
	OLED_ShowChinese(16, 0, 0,16,1);
	OLED_ShowChinese(32, 0, 2,16,1);
	OLED_ShowChinese(48, 0, 26,16,1);
	OLED_ShowChinese(64, 0, 27,16,1);	
	OLED_ShowChar(80, 0, ':',16,1);
	
	//显示"烟雾阈值:"
	OLED_ShowChinese(16, 16, 10,16,1);
	OLED_ShowChinese(32, 16, 11,16,1);
	OLED_ShowChinese(48, 16, 26,16,1);
	OLED_ShowChinese(64, 16, 27,16,1);	
	OLED_ShowChar(80, 16, ':',16,1);
	
	//显示"一氧阈值:"
	OLED_ShowChinese(16, 32, 18,16,1);
	OLED_ShowChinese(32, 32, 19,16,1);
	OLED_ShowChinese(48, 32, 26,16,1);
	OLED_ShowChinese(64, 32, 27,16,1);	
	OLED_ShowChar(80, 32, ':',16,1);
}

/**
  * @brief  显示阈值界面1的传感器数据
  * @param  无
  * @retval 无
  */
void settingsThresholdDisplay1(void)
{
	//显示温度阈值数据
	OLED_ShowNum(96, 0, Sensorthreshold.tempValue,2, 16,1);

	//显示烟雾阈值数据
	OLED_ShowNum(96, 16, Sensorthreshold.smogValue,4, 16,1);
	
	//显示甲烷阈值数据
	OLED_ShowNum(96, 32, Sensorthreshold.COValue,4, 16,1);
}

/**
  * @brief  显示阈值界面的选择符号
  * @param  num 为显示的位置
  * @retval 无
  */
void OLED_settingsOption(uint8_t num)
{
	switch(num)
	{
		case 1:	
			OLED_ShowChar(0, 0,'>',16,1);
			OLED_ShowChar(0,16,' ',16,1);
			OLED_ShowChar(0,32,' ',16,1);
			OLED_ShowChar(0,48,' ',16,1);
			break;
		
		case 2:	
			OLED_ShowChar(0, 0,' ',16,1);
			OLED_ShowChar(0,16,'>',16,1);
			OLED_ShowChar(0,32,' ',16,1);
			OLED_ShowChar(0,48,' ',16,1);
			break;
		
		case 3:	
			OLED_ShowChar(0, 0,' ',16,1);
			OLED_ShowChar(0,16,' ',16,1);
			OLED_ShowChar(0,32,'>',16,1);
			OLED_ShowChar(0,48,' ',16,1);
			break;
		case 4:	
			OLED_ShowChar(0, 0,' ',16,1);
			OLED_ShowChar(0,16,' ',16,1);
			OLED_ShowChar(0,32,' ',16,1);
			OLED_ShowChar(0,48,'>',16,1);
			break;

		default: 
			break;
	}
}


/**
  * @brief  记录阈值界面下按KEY2的次数
  * @param  无
  * @retval 返回次数
  */
uint8_t SetSelection(void)
{
	static uint8_t count = 1;
	if(KeyNum == KEY_2)
	{
		KeyNum = 0;
		count++;
		if (count > 3)
		{
			count = 1;
		}
	}
	return count;
}

/**
  * @brief  对阈值界面的传感器阈值进行修改
  * @param  num 为当前用户需要更改的传感器阈值位置
  * @retval 无
  */
void ThresholdSettings(uint8_t num)
{
	switch (num)
	{
		case 1:
			if (KeyNum == 3)
			{
				KeyNum = 0;
				Sensorthreshold.tempValue++;
				if (Sensorthreshold.tempValue > 99)
				{
					Sensorthreshold.tempValue = 0;
				}
			}
			else if (KeyNum == 4)
			{
				KeyNum = 0;
				Sensorthreshold.tempValue--;
				if (Sensorthreshold.tempValue > 99)
				{
					Sensorthreshold.tempValue = 99;
				}				
			}
			break;
			
		case 2:
			if (KeyNum == 3)
			{
				KeyNum = 0;
				Sensorthreshold.smogValue+=10;
				if (Sensorthreshold.smogValue > 500)
				{
					Sensorthreshold.smogValue = 0;
				}
			}
			else if (KeyNum == 4)
			{
				KeyNum = 0;
				Sensorthreshold.smogValue-=10;
				if (Sensorthreshold.smogValue > 500)
				{
					Sensorthreshold.smogValue = 500;
				}				
			}
			break;
			
		case 3:
			if (KeyNum == 3)
			{
				KeyNum = 0;
				Sensorthreshold.COValue+=10;
				if (Sensorthreshold.COValue > 500)
				{
					Sensorthreshold.COValue = 0;
				}
			}
			else if (KeyNum == 4)
			{
				KeyNum = 0;
				Sensorthreshold.COValue-=10;
				if (Sensorthreshold.COValue > 500)
				{
					Sensorthreshold.COValue = 500;
				}				
			}
			break;
		
		default: break;		
	}
}

/**
  * @brief  系统自动模式下的运行
  * @param  无
  * @retval 无
  */
void AutoControl(void)
{
	//LED灯开启条件
	if (sensorData.HW)
	{
		driveData.LED_Flag=1;
	}
	else
	{
		driveData.LED_Flag=0;
	}
	
	//风扇开启条件
	if(sensorData.smog > Sensorthreshold.smogValue||sensorData.CO > Sensorthreshold.COValue||sensorData.temp > Sensorthreshold.tempValue)
	{
		driveData.Fan_Flag=1;	
	}
	else
	{
		driveData.Fan_Flag=0;
	}		
		
	//蜂鸣器开启条件
	if(sensorData.smog > Sensorthreshold.smogValue||sensorData.CO > Sensorthreshold.COValue||sensorData.temp > Sensorthreshold.tempValue||sensorData.fire )
	{
		Buzzer_ON();	
	}
	else
	{
		Buzzer_OFF();
	}	
	//阀门关闭条件
	 if (sensorData.fire || sensorData.smog > Sensorthreshold.smogValue || sensorData.CO > Sensorthreshold.COValue)
    {
        driveData.servo_Flag = 1; // 关闭阀门
    }
    else
    {
        driveData.servo_Flag = 0; // 打开阀门
    }
			
	//水泵开启条件
	if (sensorData.fire)
	{
		driveData.Bump_Flag=1;
	}
	else
	{
		driveData.Bump_Flag=0;
	}
}

		

/**
  * @brief  记录自动模式界面下按KEY2的次数
  * @param  无
  * @retval 返回次数
  */
uint8_t SetAuto(void)  
{
	if(KeyNum == KEY_2)
	{
		KeyNum = 0;
		count_a++;
		if (count_a > 2)
		{
			count_a = 1;
		}
		OLED_Clear();
	}
	return count_a;
}

/**
  * @brief  记录手动模式界面下按KEY2的次数
  * @param  无
  * @retval 返回次数
  */
uint8_t SetManual(void)
{
    if(KeyNum == KEY_2)
    {
        KeyNum = 0;
        count_m++;
        if (count_m > 4)
        {
            count_m = 1;
        }
    }
    return count_m;
}

void OLED_manualOption(uint8_t num)
{
    switch(num)
    {
        case 1: 
            OLED_ShowChar(0, 0,'>',16,1);
            OLED_ShowChar(0,16,' ',16,1);
            OLED_ShowChar(0,32,' ',16,1);
            OLED_ShowChar(0,48,' ',16,1);
            break;
        case 2:
            OLED_ShowChar(0, 0,' ',16,1);
            OLED_ShowChar(0,16,'>',16,1);
            OLED_ShowChar(0,32,' ',16,1);
            OLED_ShowChar(0,48,' ',16,1);
            break;
        case 3:
            OLED_ShowChar(0, 0,' ',16,1);
            OLED_ShowChar(0,16,' ',16,1);
            OLED_ShowChar(0,32,'>',16,1);
            OLED_ShowChar(0,48,' ',16,1);
            break;
        case 4:
            OLED_ShowChar(0, 0,' ',16,1);
            OLED_ShowChar(0,16,' ',16,1);
            OLED_ShowChar(0,32,' ',16,1);
            OLED_ShowChar(0,48,'>',16,1);
            break;
        default: break;
    }
}

void OLED_manualPage1(void)
{
	//显示"灯光"
	OLED_ShowChinese(16,0,28,16,1);	
	OLED_ShowChinese(32,0,29,16,1);	
	OLED_ShowChar(64,0,':',16,1);
	
	//显示"风扇"
	OLED_ShowChinese(16,16,33,16,1);	
	OLED_ShowChinese(32,16,34,16,1);	
	OLED_ShowChar(64,16,':',16,1);
	
	//显示"阀门"
	OLED_ShowChinese(16,32,64,16,1);	
	OLED_ShowChinese(32,32,65,16,1);	
	OLED_ShowChar(64,32,':',16,1);

	//显示"水泵"
	OLED_ShowChinese(16,48,38,16,1);	
	OLED_ShowChinese(32,48,39,16,1);	
	OLED_ShowChar(64,48,':',16,1);

}

/**
  * @brief  显示手动模式设置参数界面1
  * @param  无
  * @retval 无
  */
void ManualSettingsDisplay1(void)
{
	if(driveData.LED_Flag)
	{
		OLED_ShowChinese(96,0,40,16,1); 	//开
	}
	else
	{
		OLED_ShowChinese(96,0,42,16,1); 	//关
	}
	
	if(driveData.Fan_Flag)
	{
		OLED_ShowChinese(96,16,40,16,1); 	//开
	}
	else
	{
		OLED_ShowChinese(96,16,42,16,1); 	//关
	}
	
	if(driveData.servo_Flag==0)
	{
		OLED_ShowChinese(96,32,40,16,1); 	//开
	}
	else
	{

		OLED_ShowChinese(96,32,42,16,1); 	//关
		
	}
	
	if(driveData.Bump_Flag)
	{
		OLED_ShowChinese(96,48,40,16,1); 	//开
	}
	else
	{
		OLED_ShowChinese(96,48,42,16,1); 	//关
	}
}

/**
  * @brief  手动模式控制函数
  * @param  无
  * @retval 无
  */
void ManualControl(uint8_t num)
{
	switch(num)
	{
		case 1:	
			//显示外设开关
			if(KeyNum == KEY_3)
			{
				
				driveData.LED_Flag = 1;
					KeyNum = 0;	
			}
				
			if(KeyNum == KEY_4)
			{
				driveData.LED_Flag = 0;
					KeyNum = 0;	
			}
			break;
		case 2:	
			if(KeyNum == KEY_3)
			{
				driveData.Fan_Flag = 1;
					KeyNum = 0;	
			}
				
			if(KeyNum == KEY_4)
			{
				driveData.Fan_Flag = 0;
					KeyNum = 0;	
			}
				
		
			break;
		case 3:	
			if(KeyNum == KEY_3)
			{
				//阀门开
				driveData.servo_Flag = 0;	
     	KeyNum = 0;					
			}
				
			if(KeyNum == KEY_4)
			{
				driveData.servo_Flag = 1;
					KeyNum = 0;	
			}
				
			
			break;
		case 4:	
			if(KeyNum == KEY_3)
			{
				driveData.Bump_Flag = 1;
					KeyNum = 0;	
			}
			if(KeyNum == KEY_4)
			{
				driveData.Bump_Flag = 0;
					KeyNum = 0;	
			}
							
			break;
		default: break;
	}

}

/**
  * @brief  控制函数
  * @param  无
  * @retval 无
  */
void Control_Manager(void)
{
	if(driveData.LED_Flag)
	{
		LED_ON();
	
	}
	else
	{
		LED_OFF();
		
	}

	if(driveData.Fan_Flag)
	{
		FAN_ON;
	
	}
	else
	{
		FAN_OFF;
	
	}

	if(driveData.servo_Flag)
	{
	 Servo_SetAngle(0); 
	
	}
	else
	{
		 Servo_SetAngle(90); 
	
	}

	if(driveData.Bump_Flag)
	{
		BUMP_ON;
	
	}
	else
	{
		BUMP_OFF;
		
	}
}

void USART2_ProcessCmd(void) // 串口2接收函数
{   
    if (USART2_GetReceivedFlag()) 
    {  
        uint8_t* rx_buf = USART2_GetRxBuffer();
        switch(rx_buf[0]) 
        {
            case 'A':  // 模式切换
                if (mode == AUTO_MODE)  
                {
                    mode = MANUAL_MODE;
									  OLED_Clear();
									  count_m = 1; 
                    driveData.LED_Flag = 0;
                    driveData.Fan_Flag = 0;
									  driveData.Bump_Flag = 0;
									  driveData.servo_Flag = 1;
									 							
                }
                else if (mode == MANUAL_MODE)  
                {
                    mode = AUTO_MODE;
                  	OLED_Clear();
                }
                break;
								
            case 'B': 
                if (mode == MANUAL_MODE) 
                {
                    driveData.LED_Flag = !driveData.LED_Flag;	
                    count_m = 1;
                    
                } 
                break;

            case 'C':  
                if (mode == MANUAL_MODE)
                {
                    driveData.Fan_Flag = !driveData.Fan_Flag;
									 
                    count_m = 2;   
                }
                break;
								
								 case 'D': 
                if (mode == MANUAL_MODE)
                {
                    driveData.servo_Flag = !driveData.servo_Flag;									 
                    count_m = 3;           
                }
                break;
								
								 case 'E':  
                if (mode == MANUAL_MODE)
                {
                    driveData.Bump_Flag = !driveData.Bump_Flag;             
                    count_m = 4;
                }
                break;
   
                default: 
                break;
        }
        USART2_ClearReceivedFlag();
    }
}




int main(void)
{
	SystemInit();
	delay_init(72); 
	ADCx_Init();
	OLED_Init();
	DHT11_Init();
	LED_Init();
	BEEP_Init();
	FAN_Init();
	BUMP_Init();
	HW_Init();
	Key_Init();
	Servo_Init();
  USART2_Init();
  TIM2_Init(72-1,1000-1);  
  KeyNum = 0;
	delay_ms(1000);
	OLED_Clear();
	USART1_Config();
		
	  Sensorthreshold.tempValue = FLASH_R(FLASH_START_ADDR);
    Sensorthreshold.smogValue = FLASH_R(FLASH_START_ADDR + 2);
    Sensorthreshold.COValue = FLASH_R(FLASH_START_ADDR + 4);
    if (Sensorthreshold.tempValue > 50) Sensorthreshold.tempValue = 30;
    if (Sensorthreshold.smogValue > 500) Sensorthreshold.smogValue = 100;
    if (Sensorthreshold.COValue > 500) Sensorthreshold.COValue = 100;
	
while (1)
{
    USART2_ProcessCmd();
    SensorScan();

  
	
    // 同步界面菜单变量
    if (mode == AUTO_MODE)      menu = AUTO_MODE;
    else if (mode == MANUAL_MODE) menu = MANUAL_MODE;
    else if (mode == SETTINGS_MODE) menu = SETTINGS_MODE;

    switch (menu)
    {
        case AUTO_MODE:
        {
            static uint8_t last_auto_page = 0;
            uint8_t page = SetAuto();   
            if (page != last_auto_page) OLED_Clear();
            last_auto_page = page;

            if (page == 1) {
                OLED_autoPage1();
                SensorDataDisplay1();
            } else {
                OLED_autoPage2();
                SensorDataDisplay2();
            }

            AutoControl();
            Control_Manager();

            if (KeyNum == KEY_1) {
                KeyNum = 0;
                mode = MANUAL_MODE;
                count_m = 1;
                OLED_Clear();
            }
            if (KeyNum == KEY_Long1) {
                KeyNum = 0;
                count_s = 1;
                mode = SETTINGS_MODE;  
                OLED_Clear();
            }
            break;
        }

        case MANUAL_MODE:
        {
            uint8_t idx = SetManual();
            OLED_manualPage1();
            ManualSettingsDisplay1();
            OLED_manualOption(idx);
            ManualControl(idx);
            Control_Manager();

            if (KeyNum == KEY_1) {
                KeyNum = 0;
                mode = AUTO_MODE;
                driveData.LED_Flag = 0;
                driveData.Fan_Flag = 0;
                driveData.servo_Flag = 0;
                driveData.Bump_Flag = 0;
                OLED_Clear();
            }
            break;
        }

        case SETTINGS_MODE:
        {
            uint8_t sel = SetSelection();
            OLED_settingsPage1();
            settingsThresholdDisplay1();
            OLED_settingsOption(sel);
            ThresholdSettings(sel);

            if (KeyNum == KEY_1) {
                KeyNum = 0;
                mode = AUTO_MODE;
                OLED_Clear();
                FLASH_W(FLASH_START_ADDR, Sensorthreshold.tempValue,
                        Sensorthreshold.smogValue, Sensorthreshold.COValue);
            }
            break;
        }
        default: break;
    }
    OLED_Refresh();   // 统一刷新一次
  }
}

六、实验效果

七、包含内容

项目分享

相关推荐
m0_493934532 小时前
如何在 Go 中模拟 do-while 循环实现用户交互式重复执行
jvm·数据库·python
m0_743623922 小时前
如何用 removeChild 与 remove 方法从页面 DOM 中移除元素
jvm·数据库·python
InfinteJustice2 小时前
JavaScript中null与undefined在双等号下的特殊性
jvm·数据库·python
geBR OTTE2 小时前
mysql重置root密码(适用于5.7和8.0)
数据库·mysql·adb
m0_678485452 小时前
如何处理SQL空值填充_利用IFNULL函数保证数据完整性
jvm·数据库·python
m0_684501982 小时前
实现一个可精确定位、支持左右移动与删除的文本光标系统
jvm·数据库·python
weixin_408717772 小时前
HTML能写样式吗_style属性与内联样式风险【解答】
jvm·数据库·python
2501_914245932 小时前
Python如何计算NumPy数组的协方差矩阵_调用cov函数进行特征分析
jvm·数据库·python
踏着七彩祥云的小丑2 小时前
ORM框架自学整理
数据库