/*
系统名:基于51单片机的DHT11温湿度系统
系统使用说明:通过无线蓝牙进行数据传输,上位机需通过蓝牙调试软件向系统发送
命令获取信息,若要获取当前温度、湿度,则发送“?Z”即可。系统
将会自动回复当前温度和湿度。
注意事项:蓝牙需设置成主从模式(即通过AT命令设置蓝牙名和密码相同,再设置成
主从模式)蓝牙灯同步闪烁代表蓝牙连接成功。
*/
#include "reg51.h"
# include <intrins.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define uint unsigned int
#define uchar unsigned char
/************辅助全局变量块*****************/
char t,buf[6],buf_cnt;
bit sec,flag,send_flag;/*sec:秒信号;flag:串行口接收到命令标志;send_flag:回复数据标志*/
/************辅助全局变量块*****************/
/*************DHT11变量块*******************/
sbit io=P3^2; //DHT11数据端接单片机的P3^2口
typedef bit BOOL;//此声明一个布尔型变量即真或假
uchar data_byte;
uchar RH,RL,TH,TL; //TH保存温度,RH保存湿度
/*************DHT11变量块*******************/
//*******************************延时函数*******************************************
void delay(uchar ms)
{
uchar i;
while(ms--)
for(i=0;i<100;i++);
}
void delay1()//一个for循环大概需要8个多机器周期一个机器周期为1us晶振为12MHz也就是说本函数延时8us多此延时函数必须德稍微精确一点
{
uchar i;
for(i=0;i<1;i++);
}
void delay1ms(char t)
{
int i,j;
for(i=0;i<t;i++)
for(j=0;j<1000;j++);
}
//***************************延时函数*****************************************
//**************************DHT11模块*****************************************
void start()//开始信号
{
io=1;
delay1();
io=0;
delay(25);// 主机把总线拉低必须大于18ms保证DHT11能检测到起始信号
io=1; //发送开始信号结束后拉高电平延时20-40us
delay1();//以下三个延时函数差不多为24us符合要求
delay1();
delay1();
}
uchar receive_byte()//接收一个字节//
{
uchar i,temp;
for(i=0;i<8;i++)//接收8bit的数据
{
while(!io);//等待50us的低电平开始信号结束
delay1();//开始信号结束之后延时26us-28us以下三个延时函数
delay1();
delay1();
temp=0;//时间为26us-28us表示接收的为数据'0'
if(io==1)
temp=1; //如果26us-28us之后还为高电平则表示接收的数据为'1'
while(io);//等待数据信号高电平'0'为26us-28us'1'为70us
data_byte<<=1;//接收的数据为高位在前右移
data_byte|=temp;
}
return data_byte;
}
void receive()//接收数据
{
uchar T_H,T_L,R_H,R_L,check,num_check,i;
start();//开始信号//
io=1; //主机设为输入判断从机DHT11响应信号
if(!io)//判断从机是否有低电平响应信号//
{
while(!io);//判断从机发出 80us 的低电平响应信号是否结束//
while(io);//判断从机发出 80us 的高电平是否结束如结束则主机进入数据接收状态
R_H=receive_byte();//湿度高位
R_L=receive_byte();//湿度低位
T_H=receive_byte();//温度高位
T_L=receive_byte();//温度低位
check=receive_byte();//校验位
io=0; //当最后一bit数据接完毕后从机拉低电平50us//
for(i=0;i<7;i++)//差不多50us的延时
delay1();
io=1;//总线由上拉电阻拉高进入空闲状态
num_check=R_H+R_L+T_H+T_L;
if(num_check==check)//判断读到的四个数据之和是否与校验位相同
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
check=num_check;
}
}
}
//********************************DHT11模块*********************************************
//********************************中断服务函数块*********************************************
void ComSer() interrupt 4 //串行口中断服务函数(串口数据接收)
{
if(RI)
{
t=SBUF;
buf[buf_cnt++]=t;
RI=0;
if(t=='Z')
{
flag=1;
buf_cnt=0;
}
}
}
//********************************中断服务函数块*********************************************
//************************串行口字符(字符串)发送块******************************************
void putchar(unsigned char n)
{
SBUF=n;
while(!TI);
TI=0;
}
void puts(unsigned char *q)
{
while(*q)
putchar(*q++);
}
void Enter() //换行函数
{
putchar(0x0d);
putchar(0x0a);
}
void DispNum(unsigned char n)
{
unsigned char t[8]={0};
t[0]=n/10+'0';
t[1]=n%10+'0';
t[2]=0;
puts(t);
Enter();
}
//************************串行口字符(字符串)发送块******************************************
//********************************串行口请求判断块****************************************
void Dill()
{
if(buf[0]=='?')
{
delay1ms(50);
send_flag=1;
}
}
//********************************串行口请求判断块*********************************************
//********************************初始化函数块*********************************************
void init_com() //寄存器初始化函数
{
SCON=0x50; //串行口工作方式0,多机通信,允许接收
IE|=0X90; //定时器T1和总中断允许
PCON=0X80; //SMOD为1
TMOD|=0X21; //T1工作在方式2,T0工作在方式1
TH1=250; //T1高八位赋值
TR1=1; //T1打开
TR0=1; //T0关闭
}
//********************************初始化函数块*********************************************
void main()
{
init_com();
while(1)
{
receive(); //读取温湿度
if(send_flag)
{
send_flag=0;
puts("Wendu:");
DispNum(TH);
puts("Shidu:");
DispNum(RH);
Enter();
}
if(flag)
{
flag=0;
ES=0;
Dill(); //无线设置函数
ES=1;
}
}
}