基于STM32的温湿度采集监测报警OLED显示_proteus仿真+程序代码+设计报告+讲解
STM32的远程温湿度采集监测报警OLED显示设计
基于STM32的远程温湿度采集监测报警OLED显示设计
本设计包含proteus仿真+程序代码+设计报告+讲解视频
一、开发环境
仿真图:proteus 8.17
程序编译器:keil 5
编程语言:C语言
设计编号:C0137
二、主要功能
本次嵌入式设计综合实验的内容为基于STM32F103c8t6单片机的温湿度采集报警系统。完成OLED液晶显示、DHT11温湿度测量、指示灯、蜂鸣器控制等多项任务。
1、以STM32为最小系统电路进行连接,用OLED显示屏显示温度、湿度、温度阈值,湿度阈值。
2、用DHT11温湿度传感器进行温湿度的测量。
3、可以通过按键可以设置温湿度阈值。设置按键进入设置模式/退出设置模式,按键加减调整阈值。
4、当温度超过设置的阈值时有声光报警,对应报警指示灯点亮,蜂鸣器报警。
5、默认温度低阈值20℃,高阈值30℃,湿度低阈值50%,湿度高阈值80%。
6、云平台远程查看温湿度检测值(仿真使用串口模拟)
主要硬件设备:STM32F103C8 单片机 DHT11温湿度传感器 OLED 蜂鸣器

资料下载链接:
KEY_C0137 STM32温湿度报警器OLED显示
链接: https://pan.baidu.com/s/1lxCel6dXsWPQSoyx4RD2Dw?pwd=tqy4
提取码: tqy4
以下为本设计资料展示:
三、仿真设计
打开仿真工程,双击proteus中的单片机,选择hex文件路径,然后开始仿真。


四、程序代码
程序是用keil5 mdk版本打开的,如果打开有问题,核实下keil的版本。程序有注释可以结合讲解视频理解。

main.c
//单片机头文件
#include "stm32f10x.h"
//网络协议层
#include "onenet.h"
//网络设备
#include "esp8266.h"
//硬件驱动
#include "delay.h"
#include "usart.h"
#include "beep.h"
#include "led.h"
#include "fan.h"
#include "key.h"
#include "dht11.h"
#include "oled.h"
#include "mq2.h"
#include "fan_pwm.h"
//C库
#include <string.h>
#include <stdio.h>
// ESP8266 连接 OneNET 服务器 (MQTTs 协议,端口1883)
#define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"mqtts.heclouds.com\",1883\r\n"
// 函数声明
void Hardware_Init(void);
void Display_Init(void);
void Refresh_Data(void);
void Led_beep_sta(void);
// 全局变量
u8 temp, humi; // 温度和湿度值 (来自DHT11)
uint8_t Beep_Status; // 蜂鸣器状态标志
uint16_t set_temp_dat_l = 20; // 温度下限报警值 (低阈值)
uint16_t set_temp_dat = 30; // 温度上限报警值 (高阈值)
uint16_t set_hum_dat = 50; // 湿度下限报警值
uint16_t set_hum_dat_h = 80; // 湿度上限报警值
uint8_t Status_Change; // 状态变化标志 (代码中未实际使用)
u8 set_sta = 0; // 设置状态: 0-无编辑, 1-编辑温度下限, 2-编辑温度上限, 3-编辑湿度下限, 4-编辑湿度上限
// char data_str2[]=" "; // 注意: 原注释提到这样会越界,所以分配24字节
char data_str2[24]; // 用于OLED显示报警阈值的字符串缓冲区
/*
************************************************************
* 函数名称: main
* 函数功能: 主函数,程序入口
* 入口参数: 无
* 返回参数: 0
* 说明: 初始化硬件、连接网络,循环读取传感器数据并上传至OneNET,
* 处理云平台下发指令,刷新本地显示,控制LED和蜂鸣器
************************************************************
*/
int main(void)
{
DHT11_Data_TypeDef DHT11_Data; // DHT11 数据结构体
unsigned short timeCount = 0; // 发送间隔计数器
unsigned char *dataPtr = NULL; // 接收网络数据指针
Hardware_Init(); // 初始化外围硬件 (GPIO、串口、传感器等)
ESP8266_Init(); // 初始化ESP8266 WiFi模块
// 以下连接OneNET的代码被注释,实际产品中应取消注释
// UsartPrintf(USART_DEBUG, "Connect MQTTs Server...\r\n");
// OLED_Clear(); OLED_ShowString(0,0,"Connect MQTTs Server...",16);
// while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
// DelayXms(500);
// UsartPrintf(USART_DEBUG, "Connect MQTT Server Success\r\n");
// OLED_ShowString(0,4,"Connect MQTT Server Success",16); DelayXms(500);
// OLED_Clear(); OLED_ShowString(0,0,"Device login ...",16);
// while(OneNet_DevLink()) // 接入OneNET
// {
// ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT");
// DelayXms(500);
// }
// OneNET_Subscribe(); // 订阅云平台下发指令的主题
Display_Init(); // 初始化OLED显示界面
// Led_Set(LED_ON); // (注释) 默认开LED
Beep_Set(BEEP_OFF); // 蜂鸣器初始关闭
// 临时赋值,用于测试显示
temp = 25;
humi = 65;
while(1)
{
// 每隔约2.5秒 (50 * 50ms) 上传一次数据到OneNET
if(++timeCount >= 50)
{
// 读取DHT11温湿度传感器
if(DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) {
humi = DHT11_Data.humi_int;
temp = DHT11_Data.temp_int;
}
UsartPrintf(USART_DEBUG, "humi = %d,temp = %d \r\n", humi, temp);
// UsartPrintf(USART_DEBUG, "OneNet_SendData\r\n");
OneNet_SendData(); // 发送数据到OneNET
timeCount = 0; // 重置计数器
ESP8266_Clear(); // 清空ESP8266接收缓冲区
}
// 再次读取温湿度 (非间隔期间也频繁刷新,保证显示实时)
if(DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) {
humi = DHT11_Data.humi_int;
temp = DHT11_Data.temp_int;
}
// 检查ESP8266是否收到来自OneNET的MQTT消息
dataPtr = ESP8266_GetIPD(0);
if(dataPtr != NULL)
OneNet_RevPro(dataPtr); // 处理接收到的MQTT协议数据
Refresh_Data(); // 刷新OLED显示的数值
Led_beep_sta(); // 根据阈值控制LED和蜂鸣器
DelayMs(10); // 主循环延时10ms,避免CPU过忙
}
}
/*
************************************************************
* 函数名称: Hardware_Init
* 函数功能: 硬件初始化
* 入口参数: 无
* 返回参数: 无
* 说明: 配置中断分组、延时函数、串口(调试/ESP8266)、按键、LED、
* 蜂鸣器、DHT11、OLED等外设
************************************************************
*/
void Hardware_Init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断控制器分组设置 (2位抢占,2位响应)
Delay_Init(); // SysTick延时初始化
Usart1_Init(115200); // 串口1,用于打印调试信息
Usart2_Init(115200); // 串口2,用于驱动ESP8266
Key_Init(); // 按键初始化
Led_Init(); // LED初始化 (4个LED)
Beep_Init(); // 蜂鸣器初始化
DHT11_Init(); // DHT11温湿度传感器初始化
OLED_Init(); // OLED显示屏初始化
UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
OLED_Clear();
OLED_ShowString(0,0,"Hardware init OK",16);
DelayMs(1000);
}
/*
************************************************************
* 函数名称: Display_Init
* 函数功能: OLED显示界面初始化 (显示固定标签和当前报警阈值)
* 入口参数: 无
* 返回参数: 无
* 说明: 设置的温湿度上下限,
* 并根据set_sta在对应数值旁显示光标('^')表示正在编辑的项
************************************************************
*/
void Display_Init(void)
{
OLED_Clear();
// 第6行显示温湿度报警阈值 (根据set_sta显示光标)
if(set_sta == 0) {
sprintf(data_str2," %d--%d %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 1) { // 设置温度下限,在数值后加'^'
sprintf(data_str2,"%d^-%d %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 2) { // 设置温度上限
sprintf(data_str2,"%d--%d^ %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 3) { // 设置湿度下限
sprintf(data_str2,"%d--%d %d^-%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 4) { // 设置湿度上限
sprintf(data_str2,"%d--%d %d--%d^ ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
}
/*
************************************************************
* 函数名称: Refresh_Data
* 函数功能: 刷新OLED显示的温度、湿度数值以及报警阈值
* 入口参数: 无
* 返回参数: 无
* 说明: 将temp和humi转换为字符串显示在对应位置,
* 并根据set_sta重新绘制带有光标的阈值行
************************************************************
*/
void Refresh_Data(void)
{
char buf[5];
if(Status_Change) {
// 如果状态变化标志为真,此处预留处理 (本代码未实现)
}
else {
// 显示温度值
sprintf(buf, "%2d", temp);
OLED_ShowString(54,0,(u8*)buf,16);
// 显示湿度值
sprintf(buf, "%2d", humi);
OLED_ShowString(54,3,(u8*)buf,16);
// 重新显示报警阈值行 (与Display_Init类似,保持光标同步)
if(set_sta == 0) {
sprintf(data_str2," %d--%d %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 1) {
sprintf(data_str2,"%d^-%d %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 2) {
sprintf(data_str2,"%d--%d^ %d--%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 3) {
sprintf(data_str2,"%d--%d %d^-%d ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
if(set_sta == 4) {
sprintf(data_str2,"%d--%d %d--%d^ ", set_temp_dat_l, set_temp_dat, set_hum_dat, set_hum_dat_h);
OLED_ShowString(0,6,(u8*)data_str2,16);
}
}
}
/*
************************************************************
* 函数名称: Led_beep_sta
* 函数功能: 根据温湿度与设定阈值的比较结果,控制4个LED和蜂鸣器
* 入口参数: 无
* 返回参数: 无
* 说明: 温度高于上限 -> LED1亮;温度低于下限 -> LED2亮;
* 湿度低于下限 -> LED3亮;湿度高于上限 -> LED4亮;
* 任何一个LED亮则蜂鸣器报警
************************************************************
*/
void Led_beep_sta(void)
{
// 如果传感器读数为0或处于设置模式,不进行报警控制
if(temp == 0 || humi == 0 || set_sta != 0) {
return;
}
// 温度上限报警 (高温)
if(temp > set_temp_dat) {
LED1 = LED_ON; // 温度高于高阈值,LED1点亮
} else {
LED1 = LED_OFF; // 温度未超上限,LED1熄灭
}
// 温度下限报警 (低温)
if(set_temp_dat_l > temp) {
LED2 = LED_ON; // 温度低于低阈值,LED2点亮
} else {
LED2 = LED_OFF; // 温度高于低阈值,LED2熄灭
}
// 湿度下限报警 (干燥)
if(humi < set_hum_dat) {
LED3 = LED_ON; // 湿度低于下限,LED3点亮
} else {
LED3 = LED_OFF; // 湿度正常,LED3熄灭
}
// 湿度上限报警 (潮湿)
if(humi > set_hum_dat_h) {
LED4 = LED_ON; // 湿度高于上限,LED4点亮
} else {
LED4 = LED_OFF; // 湿度正常,LED4熄灭
}
// 如果任意一个LED处于点亮状态,则蜂鸣器报警
if(!LED1 || !LED2 || !LED3 || !LED4) {
Beep_Set(BEEP_ON);
} else {
Beep_Set(BEEP_OFF);
}
}
程序流程图:

五、设计说明书
9706字,内容包括硬件设计、软件设计、结论等。

六、资料清单&下载链接

资料下载链接:
链接: https://pan.baidu.com/s/1lxCel6dXsWPQSoyx4RD2Dw?pwd=tqy4
提取码: tqy4
更多资源 点击下方链接:
https://docs.qq.com/sheet/DS0xIa0llTmtNakRW
以下是实物图,需要定制实物可咨询!



更多推荐
所有评论(0)