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]; // 字符串缓冲区(未使用)

可以缩小

相关推荐
xyq20246 分钟前
空对象模式
开发语言
姜源Jerry13 分钟前
【Trae】Trae IDE&SOLO浅尝
java·ide·ai
宇木灵23 分钟前
C语言基础-三、流程控制语句
java·c语言·前端
不懒不懒1 小时前
【Python办公自动化进阶指南:系统交互与网页操作实战】
开发语言·python·交互
普通网友1 小时前
C++与Rust交互编程
开发语言·c++·算法
游乐码2 小时前
c#静态类和静态构造函数
开发语言·c#
小杨互联网2 小时前
项目CyberScan Pro jar软件安全成分分析插件
java·jar·软件成分分析·jar安全分析
组合缺一2 小时前
Java 版 Claude Code CLI 来了!(国产开源项目)Solon Code CLI 发布
java·ai·开源·llm·solon·cli·claudecode
散峰而望2 小时前
【算法竞赛】堆和 priority_queue
开发语言·数据结构·c++·算法·贪心算法·动态规划·推荐算法
javaIsGood_3 小时前
Java基础面试题
java·开发语言