目录
一、主要功能
1.通过DHT11模块读取环境温度和湿度:
2.将湿度、障碍物距显示在lcd1602上面,第一行显示温度和湿度,格式为:xx°Cyy%,第二行显示超声波传感器测得的距离,格式为:Distance: zzz CM:
3.判断距离是否超过设定阈值,默认阈值为150cm,当测得距离低于150cm时,蜂鸣器长鸣,LED1(黄灯)闪烁,直至恢复安全距离以上:当湿度大于65%时,蜂鸣器间断报警(需与刚才报警声有明显区别),不对LED1进行操作,如果距离和湿度两个同时满足报警条件时,距离报警优先。
4.LDR模块用于检测环境光亮度,将光敏电阳模拟信号通过ADC0832转换为数字信号传递给单片机,当亮度低于50时自动打开LED2(红色)常亮。
5.设置模块,由三个按键组成,用于修改距离阈值,当点击按键1时进入阈值设置模式,进入设置模式后点击按键2增大阈值,点击按键了减小阈值,每次变化幅度为1,lcd显示实时显示设置情况,Set Distance:sss CM,当设置完毕再次点击按键1会退出设置模式并保存刚才设定的闽值,lcd恢复原来的显示内容
二、硬件资源
基于KEIL5编写C++代码,PROTEUS8.15进行仿真,全部资源在页尾,提供安装包。
编辑
三、程序编程
#include <REGX52.H>#include <intrins.h>#include <stdio.h>#include "Delay.h"#include "LCD1602.h"#define uchar unsigned char#define uint unsigned inttypedef unsigned char u8;typedef unsigned int u16;typedef unsigned char uint8;typedef unsigned int uint16;typedef unsigned long uint32;
sbit CS=P1^0;
sbit CLK=P1^1;
sbit DIO=P1^2;
sbit Tr=P3^5;//触发信号sbit Ec=P3^6;//回响信号sbit Temp_data=P2^6; //DHT11sbit beep = P1^3;
sbit key1 = P1^4;
sbit key2 = P1^5;
sbit key3 = P1^6;
sbit led = P3^7;static int jlyz = 150;
uchar Recv_Buffer\[4\];
uint Voltage\[\]={'0','0','0','0'};
bit bdata IIC\_ERROR;unsigned int distance;unsigned int Read\_value(void);//读值函数static double u;unsigned char rec\_dat\_lcd0\[6\];unsigned char rec\_dat\_lcd1\[6\];unsigned char rec\_dat\_lcd2\[6\];unsigned char rec\_dat\_lcd3\[6\];unsigned int rec_dat\[4\];
static int wd,sd;static int flag1=0,flag2=0,flag = 0;static int ymflag=0;static int flag3=0;void DHT11\_delay\_us(unsigned char n);void DHT11\_delay\_ms(unsigned int z);void DHT11\_start();unsigned char DHT11\_rec\_byte();void DHT11\_receive();void Delay10us(void);//10us延时函数void display();void canshu();void ajpd();void Time0_Init() //定时器初始化{
TMOD = 0x21;
TH0 = 0x00;
TL0 = 0x00;
TR0 = 0;//先关闭定时器0}void Time0_Int() interrupt 1 //中断程序{
TH0 = 0xfe; //重新赋值
TL0 = 0x33;
}unsigned int Read_value(){
uint result;
Tr=1;//触发引脚发出11us的触发信号(至少10us)
Delay10us();
Tr=0; while(!Ec);//度过回响信号的低电平
TR0=1;//开启定时器0
while(Ec);//度过回响信号高电平
TR0=0;//关闭定时器0
result=((TH0\*256+TL0)\*0.034)/2; // 距离cm=(时间us * 速度cm/us)/2
return result + 2; //+2修正补偿 }//延时msvoid DHT11\_delay\_ms(unsigned int z){ unsigned int i,j; for(i=z; i>0; i--) for(j=110; j>0; j--);
}//延时us --2*n+5usvoid DHT11\_delay\_us(unsigned char n){ while(--n);
}//DHT11起始信号void DHT11_start(){
Temp\_data=1; DHT11\_delay_us(10);
Temp\_data=0; DHT11\_delay_ms(50);//这个延时不能过短,18ms以上,实际在仿真当中要想读到数据延时要在延时参数要在40以上才能出数据
Temp\_data=1; DHT11\_delay\_us(30);//这个延时不能过短}//接收一个字节unsigned char DHT11\_rec_byte(){ unsigned char i,dat=0; for(i=0; i<8; i++)
{ while(!Temp\_data); DHT11\_delay_us(8);
dat <<=1; if(Temp_data==1)
{
dat +=1;
} while(Temp_data);
} return dat;
}//接收温湿度数据void DHT11\_receive(){ unsigned int R\_H,R\_L,T\_H,T\_L; unsigned char RH,RL,TH,TL,revise; DHT11\_start();
Temp\_data=1; if(Temp\_data==0)
{ while(Temp_data==0); //等待拉高
DHT11\_delay\_us(40); //拉高后延时80us
R\_H=DHT11\_rec_byte(); //接收湿度高八位
R\_L=DHT11\_rec_byte(); //接收湿度低八位
T\_H=DHT11\_rec_byte(); //接收温度高八位
T\_L=DHT11\_rec_byte(); //接收温度低八位
revise=DHT11\_rec\_byte(); //接收校正位
DHT11\_delay\_us(25); //结束
if((R\_H+R\_L+T\_H+T\_L)==revise) //校正
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
} /*数据处理,方便显示*/
rec_dat\[0\]=RH;
rec_dat\[1\]=RL;
rec_dat\[2\]=TH;
rec_dat\[3\]=TL;
}
}void dht11(){ DHT11\_delay\_ms(150); DHT11\_receive(); sprintf(rec\_dat\_lcd0,"%d",rec\_dat\[0\]); sprintf(rec\_dat\_lcd1,"%d",rec\_dat\[1\]); sprintf(rec\_dat\_lcd2,"%d",rec\_dat\[2\]); sprintf(rec\_dat\_lcd3,"%d",rec\_dat\[3\]); DHT11\_delay_ms(100);
sd = rec\_dat\[1\]*10 + rec\_dat\[0\];
wd = rec\_dat\[3\]*10 + rec\_dat\[2\];
}uchar get\_AD\_Res() //ADC0832启动读取函数{
uchar i, data1=0, data2=0;
CS=0;
CLK=0;DIO=1;\_nop\_();
CLK=1;\_nop\_();
CLK=0;DIO=1;\_nop\_();
CLK=1;\_nop\_();
CLK=0;DIO=0;\_nop\_();
CLK=1;\_nop\_();
CLK=0;DIO=1;\_nop\_();
for(i=0; i<8; i++)
{
CLK=1;\_nop\_();
CLK=0;\_nop\_();
data1=(data1<<1)|(uchar)DIO;
}
for(i=0; i<8; i++)
{
data2=data2|(uchar)DIO<<i;
CLK=1;\_nop\_();
CLK=0;\_nop\_();
}
CS=1;
return(data1 == data2)?data1:0;
}void beep_warning(){ if(distance < jlyz)
{
flag1 = 1;
} else
{
flag1 = 2;
}
if(sd > 65)
{
flag2 = 3;
} else
{
flag2 = 4;
}
flag = flag1 * flag2; if(flag == 3 || flag == 4)
{
beep =~ beep; Delay(500);
} else if(flag == 6)
{
beep =~ beep; Delay(100);
} else if(flag == 8)
{
beep = 1;
}
if(u>=50)
{
led = 0;
} else
{
led = 1;
}
}void main() //主函数{
Tr=0; //出发引脚首先拉低
LCD_Init(); //显示屏初始化
Time0_Init(); //定时初始化
beep = 1;
led = 0; while(1)
{ canshu(); //参数获取
display(); //显示
beep_warning();//报警
ajpd(); //按键判断
}
}void ajpd(){ if(key1==0)
{ Delay(100); if(key1 == 0)
{ LCD_Init(); //显示屏初始化
ymflag++; if(ymflag>1)
{
ymflag = 0;
}
}
} if(key2==0)
{ Delay(100); if(key2 == 0)
{
jlyz++;
}
}
if(key3==0)
{ Delay(100); if(key3 == 0)
{
jlyz--;
}
}
}void canshu() {
distance = Read_value();//读值
distance+=12; dht11(); //温湿度获取
u=get\_AD\_Res();
u = (u/177)*50;
}void display(){ if(ymflag == 0)
{ LCD_ShowNum(2,10,distance,3); //显示距离
LCD\_ShowNum(1,1,wd,2); LCD\_ShowNum(1,7,sd,2);
flag3 = 0;
} else if(ymflag == 1)
{ LCD_ShowNum(2,1,jlyz,3); //显示距离
flag3 = 1;
}
if(flag3 == 0)
{ LCD_ShowString(2,1,"Distance:"); //显示字符串Distance
LCD_ShowString(2,14,"CM"); //显示字符串Distance
LCD_ShowString(1,3,"C"); //显示字符串Distance
LCD_ShowString(1,9,"%"); //显示字符串Distance
flag3 = 2;
} else if (flag3 == 1)
{ LCD_ShowString(1,1,"SetDistance"); //显示字符串Distance
LCD_ShowString(2,4,"CM");
flag3 = 2;
}
}
// void Delay10us(){
TL0=0xF5;
TH0=0xFF;
TR0=1; while (TF0==0);
TR0=0;
TF0=0;
}
四、实现现象
具体动态效果看B站演示视频:
基于单片机的超声波、温湿度、光照检测分阶段报警_哔哩哔哩_bilibili
全部资料(源程序、仿真文件、安装包、演示视频):
http:// https://pan.baidu.com/s/1nZjWADtV0UnN-OcZPSpc1Q?pwd=rqn5