九、Proteus817实现51单片机DHT22温湿度读取
前言
最近搜DHT11的时候发现还有个器件DHT22,刚好有前面的DHT11代码,仿真替换器件后,发现代码运行出错,展示的数据是错误的,后面查询得知DHT22的数据格式不一样,解析函数不一致,所以得重新写解析函数。
一、仿真
直接展示仿真的连接吧,具体可以参考本栏前面几章的仿真操作。
二、代码
这里的代码是在DHT11的基础上改的,所以一些函数和文件的DHT11我没去换,你们直接在使用的时候去分别这两个读取函数即可。
这里有几个需要注意的点
1、DHT22的数据是16位的,所以常规的DHT11的char型是不能用的,会导致数据出现问题。
2、另外读取的温湿度需要经过放缩才能使用,比如27.3,其实数据是273,我们在在代码里利用 / 和 % 去处理就可以拿出小数位。
打开keil后新建工程添加文件。
main.c
#include "intrins.h"
#include "reg52.h"
#include "string.h"
#include "DHT11.h"
#include "uart.h"void Delay1000ms(void) //@11.0592MHz
{unsigned char data i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void main()
{int temp, humi, res;UART_Init(9600);while(1){Delay1000ms();//延时res = DHT22_Read_Data(&temp,&humi);//读取数据if(res == 2){UART_SendString("Temp:");UART_SendDec(temp/10);UART_SendString(".");UART_SendDec(temp%10);UART_SendString(" Humi:");UART_SendDec(humi/10);UART_SendString(".");UART_SendDec(humi%10);UART_SendString("\r\n");}}
}
DHT11.c
#include "intrins.h"
#include "reg52.h"
#include "string.h"
#include "DHT11.h"
#include "uart.h"void Delay1000ms(void) //@11.0592MHz
{unsigned char data i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void main()
{int temp, humi, res;UART_Init(9600);while(1){Delay1000ms();//延时res = DHT22_Read_Data(&temp,&humi);//读取数据if(res == 2){UART_SendString("Temp:");UART_SendDec(temp/10);UART_SendString(".");UART_SendDec(temp%10);UART_SendString(" Humi:");UART_SendDec(humi/10);UART_SendString(".");UART_SendDec(humi%10);UART_SendString("\r\n");}}
}
DHT11.h
#ifndef _DHT11_H
#define _DHT11_H#define uchar unsigned char
#define uint unsigned int
//两个函数不要同时用
unsigned char DHT11_Read_Data(uchar *temp, uchar *humi);//返回值为读取数据状态----DHT11
unsigned char DHT22_Read_Data(uchar *temp, uchar *humi);//返回值为读取数据状态----DHT22#endif
另外还需要串口
uart.c
#include "uart.h"
#include "reg52.h"// ---- 串口初始化 (9600, 11.0592MHz 晶振) ----
void UART_Init(unsigned long baudrate)
{unsigned char reload_value;SCON = 0x50; // 模式1, 8位数据, 可变波特率TMOD &= 0x0F;TMOD |= 0x20; // 定时器1, 模式2// 使用公式计算重载值: TH1 = 256 - (晶振频率)/(384*波特率)// 注意: 这里假设使用11.0592MHz晶振reload_value = 256 - (11059200UL / (384 * baudrate));// 设置定时器1初始值TH1 = reload_value;TL1 = reload_value; // 启动定时器1TR1 = 1;// 设置发送中断标志,使能标准库函数(如printf)TI = 1;// 开启总中断EA = 1;
}// ---- 基础串口发送 ----
void UART_SendChar(unsigned char c)
{SBUF = c;while(!TI);TI = 0;
}
void UART_SendString(char *s)
{while(*s) UART_SendChar(*s++);
}// 增强的十进制输出函数(支持更多位数)
void UART_SendDec(unsigned int val)
{char buf[6]; // 最大支持65535(5位数)+结束符int pos = 0;if (val == 0) {UART_SendChar('0');return;}while (val > 0 && pos < 6) {buf[pos++] = (val % 10) + '0';val /= 10;}while (pos--) {UART_SendChar(buf[pos]);}
}// 在uart.h中添加16进制发送函数
void UART_SendHex(unsigned char hex)
{unsigned char high, low;high = hex >> 4;low = hex & 0x0F;if(high < 10)UART_SendChar(high + '0');elseUART_SendChar(high - 10 + 'A');if(low < 10)UART_SendChar(low + '0');elseUART_SendChar(low - 10 + 'A');
}
uart.h
#ifndef _UART_H
#define _UART_Hvoid UART_Init(unsigned long baudrate);
void UART_SendChar(unsigned char c);
void UART_SendString(char *s);
void UART_SendDec(unsigned int val);
void UART_SendHex(unsigned char hex);
#endif
验证
仿真导入程序后
我们可以看到数据一致,验证成功。
四、总结
DHT22和DHT11的编程区别主要在于数据处理,其他时序基本一致。