DHT11温湿度检测系统
主控:
STC89C52RC
所需模块:
DHT11温湿度传感器,蓝牙模块,LCD1602显示屏,继电器,电池,直流电机+风扇
接线:
因为LCD1602所需引脚较多,手上的是开发板,有卡槽直插,所以该引脚接线没画
分模块编程:
因为实现功能较多,既有DHT11温湿度检测,又有串口,还有LCD1602显示,所以分模块编程会让代码的整体思路非常清晰,各个模块的分工明确,只需在main函数中调用对应的功能函数即可,是个良好的编程习惯
DHT11温湿度传感器
首先把DHT11的起始信号按照时序要求写好,然后读取温湿度,用数组存放,同时判断获取的温度值是否超过阈值,超过则继电器信号脚置低电平,继电器吸合,开启风扇
在串口发送函数中对8位的数据转化为字符再发送,可在电脑串口助手中看到当前温湿度
在LCD1602显示的函数中同样对温湿度数组数据转换为字符后再用各自的数组存放,通过调用LCD1602的显示字符串函数,湿度在第一行显示,温度在第二行显示
DHT11.c:
#include <REGX52.H>
#include "Delay.h"
#include "Uart.h"
#include "LCD1602.h"
sbit DATA = P1^0; //DTH11模块数据线
char rec[5]; //接收40bit温湿度数据
char hum[8]; //湿度
char tem[8]; //温度
sbit relay = P1^4; //继电器
/**
* @brief 检测DHT11模块是否响应
* @param 无
* @retval无
*/
void DHT11_Start()
{
DATA = 1;
DATA = 0;
Delay1ms(30);
DATA = 1;
while(DATA);
while(!DATA);
Delay80us();
}
/**
* @brief DHT11读取温湿度
* @param 无
* @retval无
*/
void DHT11_ReadByte()
{
unsigned int i,j;
unsigned char temp = 0x00;
unsigned char flag;
DHT11_Start(); //最后时序电平为高
while(DATA);
for(i = 0; i < 5; i++) //读5轮,共读40bit
{
for(j = 0; j < 8; j++) //读温湿度整数或小数值,每次读8bit
{
while(!DATA);
Delay50us(); //延时50us后再去读DATA的电平
if(DATA == 1)
{
flag = 1;
}
else
{
flag = 0;
}
temp <<= 1; //每次循环左移一位,让出低位接收数据
temp |= flag; //如果flag是1则temp的最低位置1,是0则最低位置0
}
rec[i] = temp; //每获得8bit数据后放入rec数据中
}
if(rec[2] >= 25) //如果温度超过h25,则吸合继电器,风扇开启
{
relay = 0;
}
else
{
relay = 1; //温度低于26,断开继电器,风扇关闭
}
}
/**
* @brief 温湿度数据处理以及通过串口显示
* @param 无
* @retval无
*/
void Data_SerialShow()
{
unsigned char i;
DHT11_ReadByte(); //每次显示温湿度都要先读取数据
Delay1ms(1000);
for(i = 0; i < 4; i++)
{
if(i == 0){Uart_SendString("湿度:");}
if(i == 2){Uart_SendString("温度:");}
Uart_SendChar(rec[i]/10+0x30); //加0x30是为了转为char类型,因为字符0的ASCII码是0x30
Uart_SendChar(rec[i]%10+0x30);
if(i == 0 || i == 2){Uart_SendChar('.');}
}
Uart_SendString("\r\n");
}
/**
* @brief 温湿度数据处理及通过LCD1602显示
* @param 无
* @retval无
*/
void DTH11_LCDShow()
{
hum[0] = 'H';
hum[1] = ':';
hum[2] = rec[0]/10+0x30; //湿度整数
hum[3] = rec[0]%10+0x30;
hum[4] = '.';
hum[5] = rec[1]/10+0x30; //湿度小数
hum[6] = rec[1]%10+0x30;
hum[7] = '\0';
tem[0] = 'T';
tem[1] = ':';
tem[2] = rec[2]/10+0x30; //温度整数
tem[3] = rec[2]%10+0x30;
tem[4] = '.';
tem[5] = rec[3]/10+0x30; //温度小数
tem[6] = rec[3]%10+0x30;
tem[7] = '\0';
LCD_ShowString(1,2,hum); //通过LCD1602显示湿度
LCD_ShowString(2,2,tem); //通过LCD1602显示温度
}
蓝牙模块:
使用串口1将温湿度数据发送到串口助手上显示,同时蓝牙模块接到开发板TX、RX上后,用HC蓝牙助手连接上蓝牙模块,就可通过手机发送“open”,“close”指令控制风扇开启或关闭
Usart.c 中断处理函数(接收蓝牙信息):
/**
* @brief 串口中断处理函数,接收蓝牙信号
* @param 无
* @retval无
*/
void Uart_Rountine() interrupt 4
{
static unsigned int i = 0;
char temp;
if(RI)
{
RI = 0;
temp = SBUF;
if(temp == 'o' || temp == 'c')
{
i = 0;
}
Bule_Rec[i++] = temp;
if(Bule_Rec[0] == 'o' && Bule_Rec[1] == 'p') //如果RX接收到信息有“op”字符,则吸合继电器开启风扇
{
relay = 0;
Delay1ms(2000);
memset(Bule_Rec,'\0',SIZE);
}
if(Bule_Rec[0] == 'c' && Bule_Rec[1] == 'l' ) //如果RX接收到信息有“cl”字符,则断开继电器关闭风扇
{
relay = 1;
Delay1ms(2000);
memset(Bule_Rec,'\0',SIZE);
}
if(i == SIZE){i = 0;}
}
}
如果使用蓝牙控制继电器,发送“open”吸合继电器时,因为此时温度检测没超过阈值,就会立马断开继电器,所以串口中吸合继电器加了两秒的延时,吸合继电器两秒后断开,可以看到手机蓝牙控制的现象;“close”指令同理,温度超过阈值吸合继电器时,串口收到指令断开继电器两秒后,温度超过阈值会再次吸合