51单片机课程设计:基于DHT11的温湿度报警器
本程序适用于51系列单片机,主要用于读取DHT11温湿度模块数值,显示在数码管上,同时还具备温湿度报警功能,当超出预设值,蜂鸣器报警,可在吉林农业大学单片机开发板上完美运行,其他朋友可以修改部分代码移植的其他型号的开发板上。工程文件以及开发板电路图可到附件下载,同时DHT11部分资料在附件也可以下载。
关于粘贴复制乱码的问题:如果程序复制到Keil编译器上出现注释乱码,可以先建一个.c文件,也就是说不在keil里面编辑,然后用记事本打开.c文件,将源码复制进去,再在keil中添加文件即可。
/************************************说明***************************************
程序运行时 会对模块进行预热 保证读取第一个数值的精确
预热时间大概为4秒左右
程序初始化时将会提示你设置最大温湿度
H1 最高温度 L1 最低温度
H2 最高湿度 L2 最低湿度
按钮K1温度加 按钮K2温度减
设置完成后 按K3 即确定按钮 开始监控报警
(适用于吉农51单片机开发板)
2016-12-29----------------------------SWorld
********************************************************************************/
#include <reg52.h>
#define OK 1
#define ERROR 0
#define NUMBER 20
#define SIZE 5
/*-----------------------------显示部分接线方法-------------------------------*/
#define GPIO_DIG P0
sbit WEC=P2^3; //段选
sbit DUC=P2^2; //位选
/*----------------------------模块引脚连接-------------------------------------*/
sbit dht11 = P2^0; //dht 接口 只要接一个就行 接dht11 data0接口 NC不用管
/*-----------------------------按键引脚方法------------------------------------*/
sbit add=P2^5;//增加 连接K2
sbit sub=P2^4;//减少 连接K1
sbit ok=P2^6;//确定 连接K3
/*----------------------------报警引脚连接-------------------------------------*/
sbit bell=P2^7;//蜂鸣器接口 连接蜂鸣器
/*------------------------------全局变量---------------------------------------*/
unsigned char flag;
/*---------------分别代表数码管上的0~9共10位数以及字母L、H----------------------*/
unsigned char code array[12]= {
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x76//L H
};
unsigned char DisplayData[8]; //用来存放要显示的8位数的值
unsigned int HTemp,LTemp,HHumi,LHumi,setok; //用来存放最大温湿度 以及是否设置好温湿度
int temp_value, humi_value; //温湿度数值存放
unsigned char status;
unsigned char value_array[5];
/*------------------------------函数声明---------------------------------------*/
void Delay_1ms(unsigned int ms);
unsigned char ReadTempAndHumi(void);
void InitTime(void);
void Delay_1ms(unsigned int ms);
void SMG_Display(unsigned int value,unsigned int way ) ; //显示部分
unsigned char ReadValue(void);
/*------------------------------延时函数
延时1ms
---------------------------------------*/
void Delay_1ms(unsigned int ms)
{
unsigned int x, y;
for(x = ms; x > 0; x--)
{
for(y = 124; y > 0; y--);
}
}
/*------------------------------延时函数
延时10ns
---------------------------------------*/
void Delay_10us(void)
{
unsigned char i;
i--;
i--;
i--;
i--;
i--;
i--;
}
/*------------------------------读取模块数值
---------------------------------------*/
unsigned char ReadValue(void)
{
unsigned char count, value = 0, i;
status = OK;
for(i = 8; i > 0; i--)
{
value <<= 1;
count = 0;
while(dht11 == 0 && count++ < NUMBER);
if(count >= NUMBER)
{
status = ERROR;
return 0;
}
Delay_10us();
Delay_10us();
Delay_10us();
if(dht11 != 0)
{
value++;
while(dht11 != 0 && count++ < NUMBER)
{
dht11 = 1;
}
if(count >= NUMBER)
{
status = ERROR;
return 0;
}
}
}
return (value);
}
/*------------------------------获取模块温湿度
---------------------------------------*/
unsigned char ReadTempAndHumi(void)
{
unsigned char i = 0, check_value = 0,count = 0;
EA = 0;
dht11 = 0;
Delay_1ms(20);
dht11 = 1;
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
if(dht11 != 0)
{
EA = 1;
return ERROR;
}
else
{
while(dht11 == 0 && count++ < NUMBER);
if(count >= NUMBER)
{
dht11 = 1;
EA = 1;
return ERROR;
}
count = 0;
dht11 = 1;
while(dht11 != 0 && count++ < NUMBER);
if(count >= NUMBER)
{
dht11 = 1;
EA = 1;
return ERROR;
}
for(i = 0; i < SIZE; i++)
{
value_array[i] = ReadValue();
if(status == ERROR)
{
dht11 = 1;
EA = 1;
return ERROR;
}
if(i != SIZE - 1)
{
check_value += value_array[i];
}
}
if(check_value == value_array[SIZE - 1])
{
humi_value = value_array[0] * 10;
temp_value = value_array[2] * 10;
dht11 = 1;
EA = 1;
return OK;
}
else
{
EA = 1;
return ERROR;
}
}
}
/**************************************************************
键盘扫描子程序
**************************************************************/
unsigned char Key_Scan()
{
unsigned char keyValue = 0 , i; //保存键值
//--检测按键1--//
if (ok != 1)//检测按键K3是否按下
{
Delay_1ms(10);//消除抖动
if (ok != 1)//再次检测按键是否按下
{
keyValue = 3;
i = 0;
while ((i<50) && (ok != 1)) //检测按键是否松开
{
Delay_1ms(10);
i++;
}
}
}
//--检测按键1--//
if (add != 1)//检测按键K1是否按下
{
Delay_1ms(10);//消除抖动
if (add!= 1)//再次检测按键是否按下
{
keyValue = 2;
i = 0;
while ((i<50) && (add != 1)) //检测按键是否松开
{
Delay_1ms(10);
i++;
}
}
}
//--检测按键1--//
if (sub != 1)//检测按键K2是否按下
{
Delay_1ms(10);//消除抖动
if (sub!= 1)//再次检测按键是否按下
{
keyValue = 1;
i = 0;
while ((i<50) && (sub != 1)) //检测按键是否松开
{
Delay_1ms(10);
i++;
}
}
}
return keyValue; //将读取到键值的值返回
}
/*******************************************************************************
* 函 数 名 : DigDisplay
* 函数功能 : 使用数码管显示
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DigDisplay()
{
unsigned char i;
unsigned int j;
for(i=0;i<8;i++)
{
WEC=1;DUC=0;
switch(i) //位选,选择点亮的数码管,
{
case(0):
GPIO_DIG=0x7F; break;//显示第0位
case(1):
GPIO_DIG=0xBF; break;//显示第1位
case(2):
GPIO_DIG=0xDF; break;//显示第2位
case(3):
GPIO_DIG=0xEF; break;//显示第3位
case(4):
GPIO_DIG=0xF7; break;//显示第4位
case(5):
GPIO_DIG=0xFB; break;//显示第5位
case(6):
GPIO_DIG=0xFD; break;//显示第6位
case(7):
GPIO_DIG=0xFE; break;//显示第7位
}
WEC=0;DUC=1;
GPIO_DIG=DisplayData[i];//发送段码
j=50; //扫描间隔时间设定
while(j--);
GPIO_DIG=0x00;//消隐
}
}
/*------------------------------主函数
主函数共分为5部分,有switch语句执行相关操作
case 1:设置最高温度,完成设置后跳到下一循环
case 2:设置最低温度,完成设置后跳到下一循环
case 3:设置最高湿度,完成设置后跳到下一循环
case 4:设置最低湿度,完成设置后跳到下一循环
case 5:温湿度监控主循环,当低于后者超过预设值,
触发警报。所读取的数值同时显示于数码管
---------------------------------------*/
void main(void)
{
unsigned char mark = 0;
Delay_1ms(1000);
ReadTempAndHumi();
Delay_1ms(3000);
InitTime();
WEC=0;DUC=0;
HTemp=30,LTemp=20;
HHumi=100,LHumi=20;
bell=1,setok=1;
while(1)
{
switch(setok)
{
case 1:
DisplayData[7]=array[11];
DisplayData[6]=array[1];
DisplayData[4]=array[HTemp/10];
DisplayData[3]=array[HTemp%10];
switch(Key_Scan())
{
case 1:
HTemp-=2;
break;
case 2:
HTemp+=2;
break;
case 3:
setok=2;
break;
}
break;
case 2:
DisplayData[7]=array[10];
DisplayData[6]=array[1];
DisplayData[4]=array[LTemp/10];
DisplayData[3]=array[LTemp%10];
switch(Key_Scan())
{
case 1:
LTemp-=2;
break;
case 2:
LTemp+=2;
break;
case 3:
setok=3;
break;
}
break;
case 3:
DisplayData[7]=array[11];
DisplayData[6]=array[2];
DisplayData[4]=array[HHumi/100];
DisplayData[3]=array[HHumi%100/10];
DisplayData[2]=array[HHumi%10];
switch(Key_Scan())
{
case 1:
HHumi-=2;
break;
case 2:
HHumi+=2;
break;
case 3:
setok=4;
break;
}
break;
case 4:
DisplayData[7]=array[10];
DisplayData[6]=array[2];
DisplayData[4]=array[LHumi/100];
DisplayData[3]=array[LHumi%100/10];
DisplayData[2]=array[LHumi%10];
switch(Key_Scan())
{
case 1:
LHumi-=2;
break;
case 2:
LHumi+=2;
break;
case 3:
setok=5;
break;
}
break;
case 5:
DisplayData[4]=0x00;
if(flag == 30)
{
flag = 0;
mark++;
ReadTempAndHumi();
if(temp_value<LTemp*10||temp_value>HTemp*10||humi_value<LHumi*10||humi_value>HHumi*10)
{
bell=0;
}
else
{
bell=1;
}
}
SMG_Display(temp_value,0);
SMG_Display(humi_value,1);
break;
}
DigDisplay();
}
}
/*------------------------------定时器初始化
---------------------------------------*/
void InitTime(void)
{
TH0 = (unsigned char)((65535U - 50000) >> 8);
TL0 = (unsigned char)(65535U - 50000) ;
TMOD = 0X01;
TR0 = 1;
ET0 = 1;
EA = 1;
}
/*------------------------------数值转换
将读取到的数值转换为数码管可显示的数值
---------------------------------------*/
void SMG_Display(unsigned int value,unsigned int way )
{
unsigned char ge, bai, shi;
ge = value % 10;
shi = value % 100 / 10;
bai = value % 1000 / 100;
if(way==0)
{
DisplayData[7]=array[bai];
DisplayData[6]=array[shi]|0x80;
DisplayData[5]=array[ge];
}
else
{
DisplayData[3]=array[bai];
DisplayData[2]=array[shi]|0x80;
DisplayData[1]=array[ge];
}
}
/*------------------------------定时器0
---------------------------------------*/
void timer(void) interrupt 1
{
TH0 = (unsigned char)((65535 - 50000) >> 8);
TL0 = (unsigned char)(65535 - 50000);
flag++;
}
附件:http://down.51cto.com/data/2368527