Ai8051U+DHT11温湿度!

main.c

cpp 复制代码
#include "Ai8051U.h"
#include "Delay.h"
#include "Uart.h"
#include "DHT11.h"
#include <stdint.h>

// ---- 自定义全局变量 ----
uint16_t count = 0; // 全局计数变量(未使用)
__xdata char strbuff[128]; // 字符串缓冲区(未使用)
extern void UartIsr(void) __interrupt(4);
uint8_t temp, humi; // 温度和湿度变量
// ----------------------

void main(void)
{
    CKCON = 0;
    WTST = 0; // 看门狗关闭
    P0M0 = 0x00; P0M1 = 0x00; // 设置P0为准双向口
    P1M0 = 0x00; P1M1 = 0x00; // 设置P1为准双向口
    P2M0 = 0x00; P2M1 = 0x00; // 设置P2为准双向口
    P3M0 = 0x00; P3M1 = 0x00; // 设置P3为准双向口
    P4M0 = 0x00; P4M1 = 0x00; // 设置P4为准双向口
    P5M0 = 0x00; P5M1 = 0x00; // 设置P5为准双向口

    Uart_Init(115200UL); // 初始化UART,波特率115200
    DHT11_Init(); // 初始化DHT11传感器
    UartSendString("Hello,This is DHT11!\r\n");

    while (1)
    {
        if(DHT11_ReadData(&temp, &humi)) {
            // 成功读取数据
            sprintf(strbuff, "Temperature: %dC\r\n", temp);
            UartSendString(strbuff);
            sprintf(strbuff, "Humidity: %d%%\r\n", humi);
            UartSendString(strbuff);
        } else {
            UartSendString("DHT11 Read Error!\r\n");
        }
        delay_ms(2000); // 每2秒读取一次
    }
}

T0定时器自动重载 版本 main.c

cpp 复制代码
#include "Ai8051U.h"
#include "Delay.h"
#include "Uart.h"
#include "DHT11.h"
#include <stdint.h>

// ---- 自定义全局变量 ----
uint16_t count = 0;       // 全局计数变量(未使用)
__xdata char strbuff[64]; // 字符串缓冲区(未使用)
extern void UartIsr(void) __interrupt(4);
uint8_t temp, humi; // 温度和湿度变量
// ----------------------

// 函数声明
void Timer0_Init(void);
// ------
void main(void)
{
    CKCON = 0;
    WTST = 0; // 看门狗关闭
    P0M0 = 0x00;
    P0M1 = 0x00; // 设置P0为准双向口
    P1M0 = 0x00;
    P1M1 = 0x00; // 设置P1为准双向口
    P2M0 = 0x00;
    P2M1 = 0x00; // 设置P2为准双向口
    P3M0 = 0x00;
    P3M1 = 0x00; // 设置P3为准双向口
    P4M0 = 0x00;
    P4M1 = 0x00; // 设置P4为准双向口
    P5M0 = 0x00;
    P5M1 = 0x00; // 设置P5为准双向口

    Timer0_Init();       // 初始化定时器0,用于1ms中断
    Uart_Init(115200UL); // 初始化UART,波特率115200
    DHT11_Init();        // 初始化DHT11传感器
    UartSendString("Hello,This is DHT11!\r\n");

    while (1)
    {
        // 普通读取温湿度
        // if(DHT11_ReadData(&temp, &humi)) {
        //     // 成功读取数据
        //     sprintf(strbuff, "Temperature: %dC\r\n", temp);
        //     UartSendString(strbuff);
        //     sprintf(strbuff, "Humidity: %d%%\r\n", humi);
        //     UartSendString(strbuff);
        // } else {
        //     UartSendString("DHT11 Read Error!\r\n");
        // }
        // delay_ms(2000); // 每2秒读取一次

        // 判断Count变量
        if (count == 1999)
        {
            UartSendString("-------------\r\n");
            if (DHT11_ReadData(&temp, &humi))
            {
                // 成功读取数据
                sprintf(strbuff, "Temperature: %dC\r\n", temp);
                UartSendString(strbuff);
                sprintf(strbuff, "Humidity: %d%%\r\n", humi);
                UartSendString(strbuff);
            }
            else
            {
                UartSendString("DHT11 Read Error!\r\n");
            }
        }
    }
}

// 40MHZ / 1 = 40MHz  -> 1 tick = 0.025us = 25ns
// min 16 bit timer | 25ns <-> 1.638125ms(1628125ns)
void Timer0_Init(void) // 1ms@40MHz  -- 1T
{
    EA = 0;        // 关闭全局中断
    AUXR |= T0x12; // 定时器时钟1T模式(原本12T快12倍 就是1T 不是12*12=144T  -- 如快4T就是3T)
    TMOD &= 0xF0;  // 设置定时器模式
    TMOD |= 0x00;  // 定时器0,模式0,16位计数器 -- 自动重装模式
    // 1,000,000us / 25us 就是1ms需要的计数值
    TH0 = (65536 - (1000000 / 25)) >> 8;   // 设置定时初值,高8位
    TL0 = (65536 - (1000000 / 25)) & 0xFF; // 设置定时初值,低8位
    ET0 = 1;                               // 允许定时器0中断
    TR0 = 1;                               // 启动定时器0
    EA = 1;                                // 全局中断使能
}

void Timer0_Isr(void) __interrupt(1)
{
    count++; // 增加计数
    if (count >= 2000)
    {              // 每1000ms执行一次
        count = 0; // 重置计数器
    }
}

DHT11.h

cpp 复制代码
#ifndef __DHT11_H__
#define __DHT11_H__

#include "Ai8051U.h"
#include "Delay.h"
#include "Uart.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#define DHT11_PIN P00 // 定义DHT11数据引脚
#define DHT11_PIN_IO do { \
    P0M0 &= ~(1 << 0); /* 将 P0M0 的 Bit 0 清零 */ \
    P0M1 &= ~(1 << 0); /* 将 P0M1 的 Bit 0 清零 */ \
} while(0) // 使用 do-while(0) 确保宏在语法上像一个语句

void DHT11_Init(void);
bool DHT11_ReadData(uint8_t *temperature, uint8_t *humidity);

#endif // __DHT11_H__

DHT11.c

cpp 复制代码
#include "DHT11.h"

void DHT11_Init(void) {
    DHT11_PIN_IO; // 配置DHT11数据引脚为准双向口
    DHT11_PIN = 1; // 设置数据引脚为高电平
    delay_ms(100); // 延时100毫秒,等待传感器稳定
}

bool DHT11_StartSignal(void) {
    uint8_t timeout;
    
    DHT11_PIN = 0; // 拉低数据线
    delay_ms(20); // 延时20ms,符合DHT11要求
    
    DHT11_PIN = 1; // 拉高数据线
    delay_us(30); // 延时30us,符合标准时序(20-40us)
    
    DHT11_PIN = 1; // 显式置1,确保准双向口进入输入态
    timeout = 0; // 重置超时计数器
    while(DHT11_PIN == 1) {
        if(++timeout > 40) { // 大约40us超时
            UartSendString("DHT11 pull low timeout!\r\n"); // 串口打印超时信息,方便调试
            return false;
        }
        delay_us(1);
    }
    timeout = 0;
    while(DHT11_PIN == 0) {
        if(++timeout > 85) {
            UartSendString("DHT11 pull high timeout!\r\n"); 
            return false;
        }
        delay_us(1);
    }
    
    return true;
}

uint8_t DHT11_Receive_Byte(void) {
    uint8_t i;
    uint8_t byte = 0;
    for(i = 0; i < 8; i++) {
        while(DHT11_PIN); // 等待进入低电平
        while (!DHT11_PIN); // 等待50us低电平过去 
        delay_us(45); // 延时45us,判断高电平长度       
        if(DHT11_PIN == 1) {
            byte |= (1 << (7 - i)); // 接收1
            while(DHT11_PIN); // 等待高电平结束
        }
    }
    return byte;
}

bool DHT11_ReadData(uint8_t *temperature, uint8_t *humidity) {
    uint8_t data[5] = {0};
    // __xdata char strbuff[50];
    if(!DHT11_StartSignal()) {
        UartSendString("DHT11 not responding!\r\n");
        return false; // DHT11未响应
    }
    for(int i = 0; i < 5; i++) {
        data[i] = DHT11_Receive_Byte();
    }
    // 校验和验证
    if(data[4] != (data[0] + data[1] + data[2] + data[3])) {
        // sprintf(strbuff, "D1:%x D2:%x D3:%x D4:%x Checksum:%x\r\n", data[0], data[1], data[2], data[3], data[4]);
        // UartSendString(strbuff);
        UartSendString("DHT11 checksum error!\r\n");
        return false; // 校验失败
    }
    *humidity = data[0]; // 整数部分湿度
    *temperature = data[2]; // 整数部分温度
    return true;
}

效果

实际

__xdata char strbuff[128]; // 字符串缓冲区(未使用)

可以缩小

相关推荐
Highcharts.js5 小时前
倒置百分比堆叠面积图表示列详解|Highcharts大气成分图表代码
开发语言·信息可视化·highcharts·图表开发·面积图·图表示例·推叠图
csdn_aspnet5 小时前
C语言 Lomuto分区算法(Lomuto Partition Algorithm)
c语言·开发语言·算法
Dicky-_-zhang5 小时前
消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进
java·jvm
晨曦中的暮雨5 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
存在morning5 小时前
【GO语言开发实践】二 GO 并发快速上手
大数据·开发语言·golang
fake_ss1985 小时前
AI时代学习全栈项目开发的新范式
java·人工智能·学习·架构·个人开发·学习方法
茉莉玫瑰花茶6 小时前
工作流的常见模式 [ 1 ]
java·服务器·前端
未若君雅裁6 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
No8g攻城狮6 小时前
【人大金仓】wsl2+ubuntu22.04安装人大金仓数据库V9
java·数据库·spring boot·非关系型数据库
xiaoerbuyu12337 小时前
开源Java 邮箱 基于SpringBoot+Vue前后端分离的电子邮件
java·开发语言