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

相关推荐
CODECOLLECT11 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen11 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠14 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_14 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技16 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计17 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报18 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业18 小时前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能18 小时前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微
czwxkn18 小时前
4STM32(stdl)TIM定时器
stm32·单片机·嵌入式硬件