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

相关推荐
czy878747512 小时前
机智云 MCU OTA可以对MCU程序进行无线远程升级。
单片机·嵌入式硬件
麦托团子13 小时前
51单片机学习笔记17-红外遥控(外部中断)
51单片机
A9better14 小时前
嵌入式开发学习日志52——二值与计数信号量
单片机·嵌入式硬件·学习
日更嵌入式的打工仔15 小时前
(实用向)中断服务程序(ISR)的优化方向
笔记·单片机
想放学的刺客16 小时前
单片机嵌入式试题(第25)嵌入式系统可靠性设计与外设驱动异常处理
stm32·单片机·嵌入式硬件·mcu·物联网
wotaifuzao16 小时前
STM32+FreeRTOS 长期可维护架构设计(事件驱动篇)-- 告别“屎山”代码
c语言·stm32·嵌入式硬件·freertos·状态机·事件驱动·嵌入式架构
淘晶驰AK16 小时前
大学如何自学嵌入式开发?
单片机·嵌入式硬件
yantaohk16 小时前
【2025亲测】中兴B860AV3.2M完美刷机包ATV版本安卓9-解决1G运存BUG,开ADB已ROOT
android·嵌入式硬件·adb·云计算
一路往蓝-Anbo17 小时前
第 1 篇:对象池模式 (Object Pool) —— 裸机下的动态内存革命
jvm·数据库·stm32·单片机·嵌入式硬件·网络协议·tcp/ip
飞凌嵌入式17 小时前
1块集成了4核Cortex-A7高性能CPU、1颗RISC-V MCU、多种高速总线、还兼容树莓派的T153低成本开发板
linux·arm开发·嵌入式硬件·risc-v