目录
一、主要功能
二、硬件资源
三、程序编程
四、实现现象
一、主要功能
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 int
typedef 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; //DHT11
sbit 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;//开启定时器0while(Ec);//度过回响信号高电平TR0=0;//关闭定时器0result=((TH0*256+TL0)*0.034)/2; // 距离cm=(时间us * 速度cm/us)/2return result + 2; //+2修正补偿
}//延时ms
void 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+5us
void 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); //拉高后延时80usR_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:"); //显示字符串DistanceLCD_ShowString(2,14,"CM"); //显示字符串DistanceLCD_ShowString(1,3,"C"); //显示字符串DistanceLCD_ShowString(1,9,"%"); //显示字符串Distanceflag3 = 2;}else if (flag3 == 1){LCD_ShowString(1,1,"SetDistance"); //显示字符串DistanceLCD_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