前言
最近搜DHT11的时候发现还有个器件DHT22,刚好有前面的DHT11代码,仿真替换器件后,发现代码运行出错,展示的数据是错误的,后面查询得知DHT22的数据格式不一样,解析函数不一致,所以得重新写解析函数。
一、仿真
直接展示仿真的连接吧,具体可以参考本栏前面几章的仿真操作。
二、代码
这里的代码是在DHT11的基础上改的,所以一些函数和文件的DHT11我没去换,你们直接在使用的时候去分别这两个读取函数即可。
这里有几个需要注意的点
1、DHT22的数据是16位的,所以常规的DHT11的char型是不能用的,会导致数据出现问题。
2、另外读取的温湿度需要经过放缩才能使用,比如27.3,其实数据是273,我们在在代码里利用 / 和 % 去处理就可以拿出小数位。
打开keil后新建工程添加文件。
main.c
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
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
c
#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
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;
// 启动定时器1
TR1 = 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');
else
UART_SendChar(high - 10 + 'A');
if(low < 10)
UART_SendChar(low + '0');
else
UART_SendChar(low - 10 + 'A');
}
uart.h
c
#ifndef _UART_H
#define _UART_H
void 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的编程区别主要在于数据处理,其他时序基本一致。