九、Proteus817实现51单片机DHT22温湿度读取

前言

最近搜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的编程区别主要在于数据处理,其他时序基本一致。

相关推荐
mftang1 小时前
CAN总线控制段:位级结构、DLC编码、代际扩展与错误处理的系统性分析
单片机·嵌入式硬件·can总线·控制段·数据长度代码
Jason_zhao_MR9 小时前
Linux与实时控制如何兼得
linux·嵌入式硬件·机器人·工业控制
BSD_CGQ10 小时前
FSR传感器STM32 DMA高速采样工程实现(高精度、低CPU占用)
stm32·单片机·嵌入式硬件·压力传感器·源头工厂·柔性薄膜压力传感器·可变电阻压力传感器
芯岭技术郦13 小时前
32 位 ARM® Cortex®-M0+ 内核MCU普冉MS32C001-C
单片机·嵌入式硬件
骑着毛驴数星星13 小时前
STM32 CAN波特率与采样点计算,基于HAL库
stm32·单片机·嵌入式硬件
zhangrelay14 小时前
Arduino-MEGA-ESP单片机理论课笔记02-硬件-2026
笔记·单片机·嵌入式硬件
艾芯微科技14 小时前
钰泰 ETA5055V330DD1E|SOT-223 3.3V LDO,低压差、大电流线性稳压选型分享
网络·单片机·嵌入式硬件·集成测试·51单片机
新晨单片机设计15 小时前
S023A-基于STM32单片机智能插座【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·单片机智能插座
威嵌神州16 小时前
恩智浦 T1022 性能怎么样?QorIQ 架构中端工业嵌入式优势解析
嵌入式硬件
weixin_6906547416 小时前
龙迅#LT9611EX 现MIPI转HDMI1.4功能主推型号,分辨率高达4K30HZ,IC内置I2C无需外部12C控制。
嵌入式硬件·音视频·信号处理