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

相关推荐
kebidaixu2 分钟前
FreeRTOS 移植到 STM32F407VETX 记录(五)
stm32·单片机·嵌入式硬件
listhi52018 分钟前
基于单片机的步进电机控制系统
单片机·嵌入式硬件
灯琰131 分钟前
STM32L051K6U6 IAP要点记录-LL库
stm32·单片机·嵌入式硬件
Lucky_ldy1 小时前
51单片机的学习终(结合中科协的个人自用笔记)
笔记·学习·51单片机
MAR-Sky1 小时前
stc8h系列单片机使用中断号超过32的插件解决办法
单片机·嵌入式硬件
结城明日奈是我老婆2 小时前
基于stm32f103c8t6最小系统板俩块版通讯
stm32·单片机·嵌入式硬件
weixin_456808382 小时前
【沁恒蓝牙开发】从机判断主机是否使能CCCD
单片机·嵌入式硬件
深圳英康仕2 小时前
一款面向AGV智能搬运机器人的RK3588工控机的数据资料整理
嵌入式硬件·rk3588·工控机·agv·智能搬运机器人
fengfuyao9852 小时前
STM32F030 SD卡文件系统读取实例
stm32·单片机·嵌入式硬件