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