C51之温湿度检测系统(自动开关风扇)

news/2024/5/21 22:56:04/文章来源:https://blog.csdn.net/weixin_49001476/article/details/127187813

目录

DHT11 温湿度传感器

产品概述

特点

检测模块是否存在

温湿度数据管理系统

 uart.c文件

 uart.h文件

lcd1602.c文件

lcd1602.H文件

dht11.c文件

dht11.h文件

delay.c文件

delay.h文件

config.h文件

main.c文件


DHT11 温湿度传感器

产品概述

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通
空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制
![在这里插入图片描述](https://img-blog.csdnimg.cn/47c96a99f371492d8e5e74579d086692.png)

特点

  • 相对湿度和温度测量
  • 全部校准,数字输出
  • 长期稳定性
  • 超长的信号传输距离:20
  • 超低能耗:休眠
  • 4 引脚安装:可以买封装好的
  • 完全互换 : 直接出结果,不用转化

 

数据传送逻辑
只有一根数据线DATA,上官一号发送序列指令给DHT11模块,模块一次完整的数据传输为40bit,高位先
数据格式
8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
通讯过程时序图

检测模块是否存在

根据如下时序图,做通信初始化,并检测模块是否存在,功能是否正常
时序逻辑分析a : dht = 1
b dht = 0
延时30ms
c dht = 1
60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!
代码实现
//检测模块是否接在设备上
#include "reg52.h"
#include "intrins.h"
sbit ledOne = P3^7;
sbit dht = P3^3;//模块的data插在p3.3void Delay30ms() //@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void Delay60us() //@11.0592MHz
{unsigned char i;i = 25;while (--i);
}void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void check_DHT()
{//a : dht = 1dht = 1;//b :dht = 0dht = 0;//延时30msDelay30ms();//c: dht = 1dht = 1;//在60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!Delay60us();if(dht == 0){ledOne = 0;//亮灯,说明模块存在}
}void main()
{ledOne = 1;Delay1000ms();Delay1000ms();check_DHT();while(1);
}
a : dht = 1
b dht = 0
延时30ms
c dht = 1
d点;while(dht1); e while(!dht) f点:while(dht) g点:while(!dht) 有效数据都是高电
平,持续时间不一样,50us读,低电平0 高电平

 

DHT11传输0的时序分析

 DHT11传输1的时序分析

 

温湿度数据管理系统

//接线:LCD1602数据选用P0口, RS接P1.0 RW接P1.1 EN接P1.4
//DHT11:数据线接P3.3口
#include "reg52.h"
#include "intrins.h"
sbit ledOne = P3^7;
sbit dht = P3^3;//模块的data插在p3.3
sbit fengshan = P1^6;
char datas[5];
sfr AUXR = 0x8E;
#define databuffer P0 //定义8位数据线,Po端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
char temp[8];
char huma[8];
void check_busy()
{char tmp = 0x80;databuffer = 0x80;while(tmp & 0x80){//1000 0000RS = 0;RW = 1;EN = 0;_nop_();EN = 1;_nop_();_nop_();tmp = databuffer;EN = 0;_nop_();}
}
void Write_Cmd_Func(char cmd)
{check_busy();RS = 0;RW = 0;EN = 0;_nop_();databuffer = cmd;_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();
}
void Write_Data_Func(char dataShow)
{check_busy();RS = 1;RW = 0;EN = 0;_nop_();databuffer = dataShow;_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();
}
void Delay15ms() //@11.0592MHz
{unsigned char i, j;i = 27;j = 226;do{while (--j);} while (--i);
}
void Delay5ms() //@11.0592MHz
{unsigned char i, j;i = 9;j = 244;do{while (--j);} while (--i);
}
void UartInit(void) //9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x40; //配置串口工作方式1,REN不使能接收TMOD &= 0xF0;TMOD |= 0x20;//定时器1工作方式位8位自动重装TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//启动定时器
}
void sendByte(char data_msg)
{SBUF = data_msg;while(!TI);TI = 0;
}
void sendString(char* str)
{while( *str != '\0'){sendByte(*str);str++;}
}
void Delay30ms() //@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}
void Delay60us() //@11.0592MHz
{unsigned char i;i = 25;while (--i);
}
void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
void DHT11_Start()
{dht = 1;dht = 0;//延时30msDelay30ms();dht = 1;//卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht)while(dht);while(!dht);while(dht);
}
void Delay40us() //@11.0592MHz
{unsigned char i;_nop_();i = 15;while (--i);
}
void Read_Data_From_DHT()
{int i;//轮int j;//每一轮读多少次char tmp;//8bit01010110的数据char flag;DHT11_Start();for(i= 0;i < 5;i++){//8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和//卡g点:while(!dht) 有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平for(j=0;j<8;j++){while(!dht);//等待卡g点Delay40us();if(dht == 1){flag = 1;while(dht);}else{flag = 0;}tmp = tmp << 1;//每左移一次空一位tmp |= flag;//填补空的位置}datas[i] = tmp;}
}
void LCD1602_INIT()
{//(1)延时 15msDelay15ms();//(2)写指令 38H(不检测忙信号)Write_Cmd_Func(0x38);//(3)延时 5msDelay5ms();//(4)以后每次写指令,读/写数据操作均需要检测忙信号//(5)写指令 38H:显示模式设置Write_Cmd_Func(0x38);//(6)写指令 08H:显示关闭Write_Cmd_Func(0x08);//(7)写指令 01H:显示清屏Write_Cmd_Func(0x01);//(8)写指令 06H:显示光标移动设置Write_Cmd_Func(0x06);//(9)写指令 0CH:显示开及光标设置}Write_Cmd_Func(0x0c);
}
void LCD1602_showLine(char row, char col, char *string)
{switch(row){case 1:Write_Cmd_Func(0x80+col);while(*string){Write_Data_Func(*string);string++;}break;case 2:Write_Cmd_Func(0x80+0x40+col);while(*string){Write_Data_Func(*string);string++;}break;}
}
void Build_Datas()
{huma[0] = 'H';huma[1] = datas[0]/10 + 0x30;huma[2] = datas[0]%10 + 0x30;huma[3] = '.';huma[4] = datas[1]/10 + 0x30;huma[5] = datas[1]%10 + 0x30;huma[6] = '%';huma[7] = '\0';temp[0] = 'T';temp[1] = datas[2]/10 + 0x30;temp[2] = datas[2]%10 + 0x30;temp[3] = '.';temp[4] = datas[3]/10 + 0x30;temp[5] = datas[3]%10 + 0x30;temp[6] = 'C';temp[7] = '\0';
}
void main()
{Delay1000ms();UartInit();LCD1602_INIT();Delay1000ms();Delay1000ms();ledOne = 0;while(1){Delay1000ms();Read_Data_From_DHT();if(datas[2] > 24){fengshan = 0;}Build_Datas();sendString(huma);sendString("\r\n");sendString(temp);sendString("\r\n");LCD1602_showLine(1,2,huma);LCD1602_showLine(2,2,temp);}
}

代码太乱,为了解决使用了分文件来操作

依次创建delay.c,delay.h,dht11.c,dht11.h,lcd1602.c,1cd1602.h,uart.c,uart.h等文件

 uart.c文件

#include "reg52.h"
#include "config.h"
#include <string.h>sfr AUXR = 0x8E;
sbit D6 = P3^6;
char buffer[12];void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x50; //配置串口工作方式1,REN使能接收TMOD &= 0xF0;TMOD |= 0x20;//定时器1工作方式位8位自动重装TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//启动定时器EA = 1;//开启总中断ES = 1;//开启串口中断
}
void sendByte(char data_msg)//传一个字符
{SBUF = data_msg;while(!TI);TI = 0;
}void sendString(char* str)//传字符串
{while( *str != '\0'){sendByte(*str);str++;}
}void Uart_Handler() interrupt 4
{char tmp;char i;if(RI)//中断处理函数中,对于接收中断的响应{RI = 0;//清除接收中断标志位tmp = SBUF;if(tmp == ':'){i = 0;}buffer[i++] = tmp;if(buffer[0] == ':' && buffer[1] =='o' && buffer[2] == 'p'){fengshan = 0;memset(buffer,'\0',12);}if(buffer[0] == ':' && buffer[1] == 'c' && buffer[2] == 'l'){fengshan = 1;D6 = 0;Delay1000ms();Delay1000ms();memset(buffer,'\0',12);}}if(TI);
}

 uart.h文件


void UartInit(void);		//9600bps@11.0592MHzvoid sendByte(char data_msg);void sendString(char* str);

lcd1602.c文件

#include "reg52.h"
#include "intrins.h"
#include "delay.h"#define databuffer  P0 //定义8位数据线,Po端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;void check_busy()
{char tmp = 0x80;databuffer = 0x80;while(tmp & 0x80){//1000 0000RS = 0;RW = 1;EN = 0;_nop_();EN = 1;_nop_();_nop_();tmp = databuffer;EN = 0;_nop_();}
}void Write_Cmd_Func(char cmd)//写指令
{check_busy();RS = 0;RW = 0;EN = 0;_nop_();databuffer = cmd;_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();	
}void Write_Data_Func(char dataShow)//写数据
{check_busy();RS = 1;RW = 0;EN = 0;_nop_();databuffer = dataShow;_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();	
}void LCD1602_INIT()
{//(1)延时 15msDelay15ms();
//(2)写指令 38H(不检测忙信号) Write_Cmd_Func(0x38);
//(3)延时 5msDelay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置}Write_Cmd_Func(0x0c);
}void LCD1602_showLine(char row, char col, char *string)
{switch(row){case 1:Write_Cmd_Func(0x80+col);while(*string){Write_Data_Func(*string);string++;}break;case 2:Write_Cmd_Func(0x80+0x40+col);while(*string){Write_Data_Func(*string);string++;}break;}
}

lcd1602.H文件

void LCD1602_INIT();void LCD1602_showLine(char row, char col, char *string);

dht11.c文件

#include "reg52.h"
#include "delay.h"sbit dht = P3^3;//模块的data插在p3.3char datas[5];void DHT11_Start()
{dht = 1;dht = 0;//延时30msDelay30ms();dht = 1;//卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht)while(dht);while(!dht);while(dht);
}void Read_Data_From_DHT()
{int i;//轮int j;//每一轮读多少次char tmp;char flag;DHT11_Start();for(i= 0;i < 5;i++){//卡g点:while(!dht)       有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平for(j=0;j<8;j++){while(!dht);//等待卡g点Delay40us();if(dht == 1){flag = 1;while(dht);}else{flag = 0;} tmp = tmp << 1;tmp |= flag;}datas[i] = tmp;}}

dht11.h文件


void Read_Data_From_DHT();

delay.c文件

#include "intrins.h"
void Delay30ms()		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void Delay40us()		//@11.0592MHz
{unsigned char i;_nop_();i = 15;while (--i);
}void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void Delay15ms()		//@11.0592MHz
{unsigned char i, j;i = 27;j = 226;do{while (--j);} while (--i);
}
void Delay5ms()		//@11.0592MHz
{unsigned char i, j;i = 9;j = 244;do{while (--j);} while (--i);
}

delay.h文件

#include "intrins.h"void Delay30ms();		//@11.0592MHzvoid Delay40us();		//@11.0592MHzvoid Delay1000ms();		//@11.0592MHzvoid Delay15ms();		//@11.0592MHzvoid Delay5ms();		//@11.0592MHz

config.h文件


sbit ledOne = P3^7;
sbit fengshan = P1^6;

main.c文件

#include "reg52.h"
#include "intrins.h"
#include "delay.h"
#include "lcd1602.h"
#include "uart.h"
#include "dht11.h"
#include "config.h"char temp[8];
char huma[8];
extern char datas[5];void Build_Datas()//利用ascall码来转换数字,发现规律每次需加0x30
{huma[0] = 'H';huma[1] = datas[0]/10 + 0x30;huma[2] = datas[0]%10 + 0x30;huma[3] = '.';huma[4] = datas[1]/10 + 0x30;huma[5] = datas[1]%10 + 0x30;huma[6] = '%';huma[7] = '\0';temp[0] = 'T';temp[1] = datas[2]/10 + 0x30;temp[2] = datas[2]%10 + 0x30;temp[3] = '.';temp[4] = datas[3]/10 + 0x30;temp[5] = datas[3]%10 + 0x30;temp[6] = 'C';temp[7] = '\0';}void main()
{Delay1000ms();UartInit();//串口初始化LCD1602_INIT();//LCD1602初始化Delay1000ms();Delay1000ms();ledOne = 0;while(1){Delay1000ms();Read_Data_From_DHT();	if(datas[2] >= 24){fengshan = 0;}else{fengshan = 1;}Build_Datas();sendString(huma);sendString("\r\n");sendString(temp);sendString("\r\n");LCD1602_showLine(1,2,huma);LCD1602_showLine(2,2,temp);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_19428.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022/10/6——基于stm32mp157a的SPI实验

SPI总线是Motorola首先提出的全双工三线/四线同步串行总线 采用主从模式架构&#xff0c;支持多从机模式应用&#xff0c;但一般仅支持单主机&#xff0c;多从机 时钟由主机控制&#xff0c;在时钟移位脉 冲下&#xff0c;数据按位传输&#xff0c;高位在前&#xff0c;低位在…

网课查题系统-题库量全网最多

网课查题系统-题库量全网最多 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#x…

React源码分析4-深度理解diff算法

上一章中 react 的 render 阶段&#xff0c;其中 begin 时会调用 reconcileChildren 函数&#xff0c; reconcileChildren 中做的事情就是 react 知名的 diff 过程&#xff0c;本章会对 diff 算法进行讲解。 diff 算法介绍 react 的每次更新&#xff0c;都会将新的 ReactElem…

Learning With Error(LWE)问题学习

概念 又称误差还原&#xff0c;容错学习问题&#xff0c;即已知一个矩阵AAA以及一个向量&#xff0c;求解 b^Axe\hat{b}A xe b^Axe 这里eee是一个固定数值范围内随机采集的一个随机噪音向量&#xff0c;所以这个问题就转化为通过AAA和b^\hat{b}b^来还原最初的未知向量xxx 可以…

android studio2021.3.1 最新xposed模块编写指南

前言 最新的xposed框架已经从xposed到Edxposed再到Lsposed&#xff0c;虽然xposed的api依然是通用的82版本&#xff0c;但现在网上大多数的在android studio上配置xposed的教程已经有点落后了&#xff0c;因此写下这篇来记录自己安装的流程。lsposed如何安装可以看我之前的小米…

CPU 和 CPU Core 有啥区别?多核 CPU?多个 CPU?单核 CPU 为何也支持多线程呢?

由于现在大多计算机都是多核CPU&#xff0c;多线程往往会比单线程更快&#xff0c;更能够提高并发&#xff0c;但提高并发并不意味着启动更多的线程来执行。更多的线程意味着线程创建销毁开销加大、上下文非常频繁&#xff0c;你的程序反而不能支持更高的TPS。 CPU 组成 CPU 全…

JavaSE --- 学Java你应该知道的历史

目录 一. Java的历史 1. Java的发明人詹姆斯高斯林 2. Java的logo 3. java的发展 二. Java 语言的特性 &#x1f416;&#x1f416;&#x1f416;&#x1f416;如果喜欢&#xff01;&#xff01;&#x1f402;&#x1f402;&#x1f402;&#x1f402; &#x1f416;&#x1f4…

创建PyQt项目需要配置三个的External Tools

1. Qt Designer&#xff1a;Qt设计器 Qt Designer D:\PyQtLearning\venv\Lib\site-packages\QtDesigner\designer.exe $ProjectFileDir$ 2. PyUIC&#xff1a;将.ui文件转换为.py文件 PyUIC D:\PyQtLearning\venv\Scripts\pyuic5.exe -o $FileNameWithoutExtension$.py $Fi…

Apache HBase API及备份与还原

一、Apache HBase API Apache HBase也适用于多个外部API。有关更多信息&#xff0c;请参阅Apache HBase外部API&#xff08;将在下一节的内容中介绍&#xff09;。 有关使用本机HBase API的信息&#xff0c;请参阅User API Reference和HBase API章节。 示例&#xff1a; 使…

JVM-2.垃圾回收

目录 一、如何判断对象可以回收 1.1 引用计数法 1.2 可达性分析算法 二、五种引用 2.1 强引用 2.2 软引用&#xff08;SoftReference&#xff09; 2.3 弱引用&#xff08;WeakReference&#xff09; 2.4 虚引用&#xff08;PhantomReference&#xff09; 2.5 终结器引…

07 hook学习01

hook学习01Hooks理解useStateuseEffect自定义hook函数Hooks理解 react组件分为类组件和函数组件 函数组件是一个更加匹配react的设计理念UI f(data)&#xff0c;利于逻辑拆分与重用的组件表达形式&#xff0c;而之前的函数组件是不可以有自己的状态的&#xff0c;为了能让函…

第二章:微服务架构构建

第二章&#xff1a;微服务架构构建 2.1&#xff1a;IDEA新建project工作空间 父工程步骤 New Project 聚合总父工程名字 Maven版本选择 字符编码 注解生效激活 Java编译版本选择8 父工程pom文件 <?xml version"1.0" encoding"UTF-8"?&g…

谷粒商城 nacos

下载nacos&#xff1a;https://github.com/alibaba/nacos/releases启动 startup.cmd -m standalone依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></depende…

(附源码)计算机毕业设计ssm大学生健康系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Vue学习第37天——.sync修饰符、$attrs和$listeners属性的使用场景和案例

目录一、.sync修饰符作用使用场景使用方法案例.sync修饰符的优势二、$attrs作用使用场景使用方法案例$attrs注意点三、$listeners作用使用场景使用方法案例$listeners注意点一、.sync修饰符 作用 之前组件进行双向绑定时&#xff0c;需要通过proos进行父传子&#xff0c;再通…

Python 实现DNS查询放大攻击

查询放大攻击的原理是&#xff0c;通过网络中存在的DNS服务器资源&#xff0c;对目标主机发起的拒绝服务攻击&#xff0c;其原理是伪造源地址为被攻击目标的地址&#xff0c;向DNS递归服务器发起查询请求&#xff0c;此时由于源IP是伪造的&#xff0c;固在DNS服务器回包的时候&…

六自由度模拟飞行C++教程

六自由度模拟飞行C教程 带引导、控制和导航 课程英文名&#xff1a;Flight Dynamics in Six Degrees of Freedom 此视频教程共14.5小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码附件全 下载地址 百度网盘地址&#xff1a;https://pan.baidu.com…

云原生|kubernetes|k8s集群测试时的一些基本操作

前言&#xff1a; kubernetes集群作为一个能够明显提升生产力的工具&#xff0c;还是需要多多练习一些基本操作的&#xff0c;我说的基本操作主要是针对基本的测试环节而不是生产环境下的操作。例如&#xff0c;在生产环境下用命令行启动一个pod并通过NodePort把这个pod运行的…

前端性能优化 - 华为面试题

前端性能优化面试题 前端性能优化总体来说分为 &#xff1a;优化请求、打包优化、代码优化 。 文章目录前端性能优化面试题Ⅰ、如何优化请求图片方面① 精灵图 ② 小图标 Base64③ 图片懒加载④ 图标库 采用 svg请求内容方面 ① 减少请求内容大小 ②更改请求方式③ 防抖节流④…

PyCharm 的初始设置

PyCharm 的官方网站地址&#xff1a;https://www.jetbrains.com/pycharm/ 教育版下载地址&#xff1a;https://www.jetbrains.com/pycharm-edu/download/#sectionlinux 专业版下载地址&#xff1a;https://www.jetbrains.com/pycharm/download/#sectionlinux 1、恢复 PyCharm …