目录
一、前言
项目成品图片:
哔哩哔哩视频链接:
STM32智能恒温箱|恒温恒湿系统
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的智能恒温箱
功能如下:
- 通过DHT11获取温湿度,当超过设置的温湿度,进行加热制冷加湿除湿,并声光报警
- 通过按键设置温湿度上下限值
- 通过OLED显示数据
- 通过蓝牙将数据远程发送到手机APP上,手机APP可以远程控制加热制冷加湿除湿
2.主要器件
- STM32F103C8T6单片机
- OLED 屏幕
- DHT11温湿度传感器
- BT04A蓝牙模块
- 继电器
- 有源蜂鸣器
- 加热片
- 制冷片
- 风扇模块
- 加湿器模块
- LED灯
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "dht11.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组
Delay_Init(); //延时初始化
Gpio_Init(); //IO初始化
Key_Init(); //按键初始化
Oled_Init(); //OLED初始化
Oled_Clear_All(); //清屏
Usart1_Init(9600); //串口1初始化,由于蓝牙通信
Oled_ShowString(1,5,"DHT11"); //DHT11温湿度传感器初始化
Oled_ShowCHinese(2,2,"初始化中");
while(DHT11_Init());
//清屏
Delay_ms(1000);
Delay_ms(1000);
Oled_Clear_All();
while(1)
{
key_num = Chiclet_Keyboard_Scan(0); //按键扫描
if(key_num != 0) //有按键按下
{
switch(key_num)
{
case 1: //按键1:切换界面
flag_display++;
if(flag_display >= 5)
flag_display = 0;
Oled_Clear_All();
break;
case 2: //按键2:加键
switch(flag_display)
{
case 0: //界面0:切换手动模式
flag_mode = 1;
break;
case 1: //界面1:温度最大值+1
if(temp_max < 99)
temp_max++;
break;
case 2: //界面2:温度最小值+1
if(temp_min < temp_max-1)
temp_min++;
break;
case 3: //界面3:湿度最大值+1
if(humi_max < 99)
humi_max++;
break;
case 4: //界面4:湿度最小值+1
if(humi_min < humi_max-1)
humi_min++;
break;
default:
break;
}
break;
case 3: //按键3:减键
switch(flag_display)
{
case 0: //界面0:切换自动模式
flag_mode = 0;
break;
case 1: //界面1:温度最大值-1
if(temp_max > temp_min+1)
temp_max--;
break;
case 2: //界面2:温度最小值-1
if(temp_min > 0)
temp_min--;
break;
case 3: //界面3:湿度最大值-1
if(humi_max > humi_min+1)
humi_max--;
break;
case 4: //界面4:湿度最小值-1
if(humi_min > 0)
humi_min--;
break;
default:
break;
}
break;
default:
break;
}
}
if(flag_display == 0) //测量界面
{
if(time_num % 10 == 0) //约2s检测一次、获取温湿度
{
Dht11_Get_Temp_Humi_Value(&temp_value,&humi_value);
}
if(time_num % 20 == 0) //蓝牙上传温湿度数据
{
UsartPrintf(USART1,"Temp:%d.%dC\r\nHumi:%d.%d%%\r\n",temp_value/10,temp_value%10,humi_value/10,humi_value%10);
}
}
switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
{
case 0: //界面0:测量界面,显示温湿度值,模式
Oled_ShowCHinese(1, 0, "温度:");
sprintf(display_buf,"%d.%dC ",temp_value/10,temp_value%10);
Oled_ShowString(1, 6, display_buf);
Oled_ShowCHinese(2, 0, "湿度:");
sprintf(display_buf,"%d.%d%% ",humi_value/10,humi_value%10);
Oled_ShowString(2, 6, display_buf);
if(flag_mode == 0)
Oled_ShowCHinese(3,0,"当前自动模式");
else
Oled_ShowCHinese(3,0,"当前手动模式");
break;
case 1: //界面1:显示设置温度最大值
Oled_ShowCHinese(1,0,"设置温度最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 2: //界面2:显示设置温度最小值
Oled_ShowCHinese(1,0,"设置温度最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 3: //界面3:显示设置湿度最大值
Oled_ShowCHinese(1,0,"设置湿度最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",humi_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 4: //界面4:显示设置湿度最小值
Oled_ShowCHinese(1,0,"设置湿度最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",humi_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
default:
break;
}
if(flag_display == 0) //测量界面
{
if(flag_mode == 0) //如果处于自动模式
{
if(temp_value > temp_max*10) //温度超过最大值,开启制冷
{
RELAY_ZL = 1;
RELAY_JR = 0;
alarm_temp = 1;
}
else if(temp_value < temp_min*10) //如果温度小于最小值,开启加热
{
RELAY_ZL = 0;
RELAY_JR = 1;
alarm_temp = 1;
}
else //如果在设置的上下限之间,关闭加热制冷
{
RELAY_ZL = 0;
RELAY_JR = 0;
alarm_temp = 0;
}
if(humi_value > humi_max*10) //如果湿度超过最大值,开启除湿
{
RELAY_CS = 1;
RELAY_JS = 0;
alarm_humi = 1;
}
else if(humi_value < humi_min*10) //如果湿度小于最小值,开启加湿
{
RELAY_CS = 0;
RELAY_JS = 1;
alarm_humi = 1;
}
else //如果在设置的上下限之间,关闭加湿除湿
{
RELAY_CS = 0;
RELAY_JS = 0;
alarm_humi = 0;
}
if(alarm_temp == 1 || alarm_humi == 1) //如果有异常、那么声光报警
{
if(time_num % 5 == 0)
{
LED = ~LED;
BEEP = ~BEEP;
}
}
else
{
LED = 0;
BEEP = 0;
}
}
else //手动模式,关闭声光报警
{
alarm_humi = 0;
alarm_temp = 0;
LED = 0;
BEEP = 0;
}
if(USART1_WaitRecive() == 0) //如果接收到数据
{
switch (usart1_buf[0]) //判断接受到什么数据
{
case 'A': //开加热、切换手动模式
flag_mode = 1;
jr_flag++;
if(jr_flag%2==1)
{
RELAY_JR = 1;
RELAY_ZL = 0;
zl_flag = 0;
}
else
RELAY_JR = 0;
break;
case 'B': //关加热、切换手动模式
flag_mode = 1;
zl_flag++;
if(zl_flag%2==1)
{
RELAY_JR = 0;
RELAY_ZL = 1;
jr_flag = 0;
}
else
RELAY_ZL = 0;
break;
case 'C': //开除湿、切换手动模式
flag_mode = 1;
cs_flag++;
if(cs_flag%2==1)
{
RELAY_CS = 1;
RELAY_JS = 0;
js_flag = 0;
}
else
RELAY_CS = 0;
break;
case 'D': //关除湿、切换手动模式
flag_mode = 1;
js_flag++;
if(js_flag%2==1)
{
RELAY_CS = 0;
RELAY_JS = 1;
cs_flag = 0;
}
else
RELAY_JS = 0;
break;
case 'E': //切换自动模式
flag_mode = 0;
break;
default:
break;
}
USART1_Clear();
}
}
else //设置界面,关闭所有继电器、声光报警
{
RELAY_JR = 0;
RELAY_ZL = 0;
RELAY_CS = 0;
RELAY_JS = 0;
LED = 0;
BEEP = 0;
}
time_num++; //计时变量+1
Delay_ms(10);
if(time_num %10 == 0)
LED_SYS = ~LED_SYS;
if(time_num >= 5000)
{
time_num = 0;
}
}
}
六、实验效果
七、资料内容