中国新兴建设招聘网站,江西响应式网站制作,南宁公司网站建设公司哪家好,白城网站建设DHT11 是一款温湿度复合传感器#xff0c;常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解#xff1a;
一、传感器概述
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感…
DHT11 是一款温湿度复合传感器常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解
一、传感器概述
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件并与一个高性能 8 位单片机相连接。
二、主要特点
体积小、功耗低适合集成到各种小型电子设备中。数字信号输出无需复杂的模拟信号处理直接输出数字信号方便与单片机进行通信。响应速度快能够快速准确地测量环境温湿度变化。精度较高温度测量范围为 0℃ - 50℃精度为 ±2℃湿度测量范围为 20% - 90% RH精度为 ±5% RH。
三、工作原理
传感器通过单片机的一个 I/O 口进行通信。单片机向 DHT11 发送启动信号后DHT11 开始采集温湿度数据。采集完成后DHT11 将温湿度数据转换为数字信号并通过数据线逐位发送给单片机。单片机接收到数据后进行校验和处理以确保数据的准确性。
四、通信协议
单片机与 DHT11 之间采用单总线数据格式进行通信。通信过程包括初始化、发送启动信号、接收数据等步骤。初始化时单片机将数据线拉低一段时间然后释放数据线等待 DHT11 的响应。发送启动信号时单片机将数据线拉低至少 18ms然后释放数据线等待 DHT11 的响应。DHT11 接收到启动信号后会发送一个 80μs 的低电平响应信号接着发送 80μs 的高电平响应信号表示准备好发送数据。DHT11 发送的数据包括 40 位分别为 8 位湿度整数数据、8 位湿度小数数据、8 位温度整数数据、8 位温度小数数据和 8 位校验和。数据以低位在前的方式逐位发送。单片机接收到数据后进行校验和计算。如果校验和正确则表示数据接收成功否则需要重新进行数据采集。
五、使用方法
硬件连接将 DHT11 的 VCC 引脚连接到单片机的电源引脚GND 引脚连接到地DATA 引脚连接到单片机的一个 I/O 口。软件编程在单片机程序中需要实现 DHT11 的初始化、启动信号发送、数据接收和校验等功能。可以使用定时器或延时函数来满足通信协议的时序要求。 操作时序 复位信号和响应信号 被调函数DTH11
#include reg52.h
#include delay.hsbit dht P3^6; // 定义连接 DHT11 传感器的引脚这里连接到 P3.6
char datas[5]; // 用于存储从 DHT11 读取的数据/*
DHT11 的时序逻辑分析
a : dht 1 设置引脚为高电平。
b £ºdht 0 将引脚拉低。
ÑÓʱ30ms 延时 30 毫秒。
c£º dht 1 将引脚拉高。
在 60us 后读 d 点如果 d 点是低电平被模块拉低说明模块存在。
*/void DH11_Star() {dht 1; // 设置引脚为高电平dht 0; // 将引脚拉低Delay30ms(); // 延时 30 毫秒发送启动信号给 DHT11dht 1; // 将引脚拉高// 卡 d 点等待 DHT11 拉低引脚作为响应开始信号while (dht);// 卡 e 点等待 DHT11 释放引脚变为高电平表示准备发送数据while (!dht);// 卡 f 点等待 DHT11 再次拉高引脚确认准备发送数据while (dht);
}void Read_Data() {int i; // 用于循环计数表示读取的数据组数这里共 5 组数据int j; // 用于循环计数表示每组数据中的每一位char temp; // 临时变量用于存储每一位数据在移位过程中的值char flag; // 标志位用于表示读取到的数据位是 1 还是 0DH11_Star(); // 调用启动 DHT11 的函数for (i 0; i 5; i) {// 卡 g 点等待 DHT11 将引脚拉低表示开始发送一组数据while (!dht);// 有效数据都是高电平持续时间不一样延时 50us 后根据引脚电平判断数据是 0 还是 1for (j 0; j 8; j) {while (!dht); // 等待引脚拉低表示开始读取一位数据Delay40us(); // 延时 40 微秒根据引脚在这个时间后的电平判断数据位if (dht 1) {flag 1; // 如果引脚为高电平标志位设为 1表示读取到的数据位是 1while (dht); // 等待引脚再次拉低准备读取下一位数据} else {flag 0; // 如果引脚为低电平标志位设为 0表示读取到的数据位是 0}temp temp 1; // 将 temp 左移一位为存储下一位数据做准备temp | flag; // 将标志位的值存入 temp完成一位数据的读取}datas[i] temp; // 将读取到的一组数据存储到 datas 数组中}
}
delay函数
#include intrins.h
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 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);
}
LCD1602
#include reg52.h
#include intrins.h
#include delay.h#define databuffer P0 // 定义 8 位数据总线连接到 P0 端口sbit RS P1^0; // 寄存器选择引脚连接到 P1.0
sbit RW P1^1; // 读写选择引脚连接到 P1.1
sbit EN P1^4; // 使能引脚连接到 P1.4/*
RSRegister Select- P1.0- 当 RS 0 时选择指令寄存器当 RS 1 时选择数据寄存器。
RWRead/Write- P1.1- 当 RW 0 时进行写操作当 RW 1 时进行读操作。
EEnable- P1.4- 下降沿触发数据传输。*/void check_busy() {char temp 0x80; // 初始化为 1000 0000用于读取忙碌标志位databuffer 0x80;// 当单片机给 1602 发送数据时通过检查忙碌标志位来避免死循环。// 高电平表示忙碌在读取时序中此时模块不能接收命令。如果为低电平表示不忙碌。while (temp 0x80) {// 进入读时序RS 0; // 设置为指令寄存器RW 1; // 设置为读操作EN 0;_nop_(); // 空操作可能用于延时等待稳定EN 1;_nop_();_nop_();temp 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) {// 将当前字符写入数据寄存器以显示在 LCD 上Write_data_Func(*string);// 指针指向下一个字符string;}break;case 2:// 设置第二行的显示地址Write_Cmd_Func(0x80 0x40 col);while (*string) {Write_data_Func(*string);string;}break;}
}
主函数
#include reg52.h
#include intrins.h
#include delay.h
#include uart.h
#include lcd1602.h
#include dht11.h
#include config.h// 定义用于存储温度和湿度显示字符串的字符数组
char temp[8];
char huma[8];
// 声明外部变量 datas可能用于存储从 DHT11 传感器读取的数据
extern char datas[5];// 函数用于构建温度和湿度的显示字符串
void build_datas() {// 将湿度的标识字符 H 存入 huma 数组的第一个位置huma[0] H;// 将 datas 数组中第一个元素湿度整数部分的十位数字转换为 ASCII 码存入 huma 数组的第二个位置huma[1] datas[0]/10 0x30;// 将 datas 数组中第一个元素湿度整数部分的个位数字转换为 ASCII 码存入 huma 数组的第三个位置huma[2] datas[0]%10 0x30;// 存入小数点huma[3] .;// 将 datas 数组中第二个元素湿度小数部分的十位数字转换为 ASCII 码存入 huma 数组的第四个位置huma[4] datas[1]/10 0x30;// 将 datas 数组中第二个元素湿度小数部分的个位数字转换为 ASCII 码存入 huma 数组的第五个位置huma[5] datas[1]%10 0x30;// 存入百分号huma[6] %;// 字符串结束标志huma[7] \0;// 将温度的标识字符 T 存入 temp 数组的第一个位置temp[0] T;// 将 datas 数组中第三个元素温度整数部分的十位数字转换为 ASCII 码存入 temp 数组的第二个位置temp[1] datas[2]/10 0x30;// 将 datas 数组中第三个元素温度整数部分的个位数字转换为 ASCII 码存入 temp 数组的第三个位置temp[2] datas[2]%10 0x30;// 存入小数点temp[3] .;// 将 datas 数组中第四个元素温度小数部分的十位数字转换为 ASCII 码存入 temp 数组的第四个位置temp[4] datas[3]/10 0x30;// 将 datas 数组中第四个元素温度小数部分的个位数字转换为 ASCII 码存入 temp 数组的第五个位置temp[5] datas[3]%10 0x30;// 存入摄氏度符号temp[6] C;// 字符串结束标志temp[7] \0;
}int main() {// 延时 1000 毫秒Delay1000ms();// 初始化串口UartInit();// 初始化 LCD1602LCD1602_Init();// 再次延时 1000 毫秒Delay1000ms();Delay1000ms();// 设置 ledOne 为 0可能用于控制某个 LEDledOne 0;while (1) {// 延时 1000 毫秒Delay1000ms();// 读取 DHT11 传感器的数据Read_Data();// 如果温度datas[2]大于等于 24if (datas[2] 24) {// 设置风扇状态为关闭fengshan 可能是一个变量用于控制风扇fengshan 0;} else {// 否则设置风扇状态为开启fengshan 1;}// 构建温度和湿度的显示字符串build_datas();// 发送湿度字符串到串口sent_string(huma);// 发送回车换行符到串口sent_string(\r\n);// 发送温度字符串到串口sent_string(temp);// 发送回车换行符到串口sent_string(\r\n);// 在 LCD1602 的第一行第二列开始显示湿度字符串LCD1602_showline(1, 2, huma);// 在 LCD1602 的第二行第二列开始显示温度字符串LCD1602_showline(2, 2, temp);}
}
成功实现