DHT11课程设计学习记录

BoxCat 2025-11-24 124 11/24

前言:

在课程设计中选择了DHT11和LCD1602作为微机原理的课程设计任务。其中,单片机是AT89C52(51/52单片机)设计程序。

首先,展示代码。

Main函数

#include <reg52.h>
#include "LCD1602.h"
#include "dht11.h"
sbit Key_Add = P3^0;
sbit Key_Sub = P3^1;
sbit Buzzer  = P2^5;
void Delay_Main_Ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 110; j++);
}
unsigned char Key_Scan(void)
{
    static unsigned char key_up = 1;
    if(Key_Add==1 && Key_Sub==1) key_up = 1;
    if(key_up == 1)
    {
        if(Key_Add == 0)
        {
            Delay_Main_Ms(10);
            if(Key_Add == 0) { key_up = 0; return 1; }
        }
        else if(Key_Sub == 0)
        {
            Delay_Main_Ms(10);
            if(Key_Sub == 0) { key_up = 0; return 2; }
        }
    }
    return 0;
}
void main(void)
{
    unsigned char set_temp = 30;
    unsigned char key_val = 0;
    unsigned int time_count = 0;
    Buzzer = 1; 
    LCD_Init();
    LCD_ShowString(1, 1, "DHT11 Sensor SYS");
    LCD_ShowString(2, 1, "Wait Connect...");
    Delay_Main_Ms(1000); 
    LCD_ShowString(1, 1, "Temp:   C       ");
    LCD_ShowString(2, 1, "Humi:   % SET:  ");
    LCD_ShowNum(2, 15, set_temp, 2);
    while(1)
    {
        key_val = Key_Scan();
        if(key_val != 0)
        {
            if(key_val == 1)
            {
                if(set_temp < 99) set_temp++;
            }
            else if(key_val == 2)
            {
                if(set_temp > 0) set_temp--;
            }
            LCD_ShowNum(2, 15, set_temp, 2);
        }
        time_count++;
        if(time_count >= 100) 
        {
            time_count = 0;
            Read_Data_From_DHT();
            LCD_ShowNum(1, 6, DHT_Datas[0], 2);
            LCD_ShowNum(2, 6, DHT_Datas[2], 2);
            if(DHT_Datas[0] >= set_temp)
            {
                Buzzer = 0;
            }
            else
            {
                Buzzer = 1;
            }
        }
        Delay_Main_Ms(10);
    }
}

接下来,DHT11驱动程序。

#include <reg52.h>
#include <intrins.h>
#include "dht11.h"

sbit dht = P3^7; 

unsigned char U8FLAG;
unsigned char U8temp;
unsigned char U8comdata;

unsigned char DHT_Datas[5] = {0};

unsigned char U8T_data_H_temp, U8T_data_L_temp, U8RH_data_H_temp, U8RH_data_L_temp, U8checkdata_temp;

void Delay_10us2(void)
{
    unsigned char i;
    i = 2;
    while (--i);
}

void Delay2(unsigned int j)
{
    unsigned char i;
    for (; j > 0; j--)
    {
        for (i = 0; i < 100; i++);
    }
}

void COM(void)
{
    unsigned char i;
    for (i = 0; i < 8; i++)
    {
        U8FLAG = 2;
        while ((!dht) && U8FLAG++);
        
        Delay_10us2();
        Delay_10us2();
        Delay_10us2();
        
        U8temp = 0;
        if (dht) U8temp = 1;
        
        U8FLAG = 2;
        while ((dht) && U8FLAG++);
        
        if (U8FLAG == 1) break;
        
        U8comdata <<= 1;
        U8comdata |= U8temp;
    }
}

void Read_Data_From_DHT(void)
{
    EA = 0;
    
    dht = 0;
    Delay2(180);
    dht = 1;
    
    Delay_10us2();
    Delay_10us2();
    Delay_10us2();
    Delay_10us2();
    
    dht = 1;
    
    if (!dht)
    {
        U8FLAG = 2;
        while ((!dht) && U8FLAG++);
        
        U8FLAG = 2;
        while ((dht) && U8FLAG++);
        
        COM();
        U8RH_data_H_temp = U8comdata;
        COM();
        U8RH_data_L_temp = U8comdata;
        COM();
        U8T_data_H_temp = U8comdata;
        COM();
        U8T_data_L_temp = U8comdata;
        COM();
        U8checkdata_temp = U8comdata; 
        
        dht = 1; 
        
        U8temp = (U8T_data_H_temp + U8T_data_L_temp + U8RH_data_H_temp + U8RH_data_L_temp);
        if (U8temp == U8checkdata_temp)
        {

            DHT_Datas[0] = U8T_data_H_temp;
            DHT_Datas[1] = U8T_data_L_temp;
            DHT_Datas[2] = U8RH_data_H_temp;
            DHT_Datas[3] = U8RH_data_L_temp;
            DHT_Datas[4] = U8checkdata_temp;
        }
    }
    
    EA = 1;
}

接下来,LCD1602驱动程序:

#include "LCD1602.h"
static void delay_ms_proteus(unsigned int ms);
static void LCD_WriteCommand(unsigned char Command);
static void LCD_WriteData(unsigned char Data);


static void delay_ms_proteus(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 500; j++); 


static void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_DATA_PORT = Command;
    LCD_EN = 1;
    delay_ms_proteus(1);
    LCD_EN = 0;
    delay_ms_proteus(1);
}

static void LCD_WriteData(unsigned char Data)
{
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_DATA_PORT = Data;
    LCD_EN = 1;
    delay_ms_proteus(1);
    LCD_EN = 0;
    delay_ms_proteus(1);
}


void LCD_Init()
{
    delay_ms_proteus(20);   
    LCD_WriteCommand(0x38);
    delay_ms_proteus(5);
    LCD_WriteCommand(0x0C);
    delay_ms_proteus(5);
    LCD_WriteCommand(0x06);
    delay_ms_proteus(5);
    LCD_WriteCommand(0x01);
    delay_ms_proteus(5);
}


void LCD_Clear(void)
{
    LCD_WriteCommand(0x01);
    delay_ms_proteus(5);
}

void LCD_ShowString(unsigned char Line, unsigned char Column, char *String)
{
    unsigned char addr;
    if (Line == 1)
        addr = 0x80 + (Column - 1);
    else
        addr = 0xC0 + (Column - 1);
    
    LCD_WriteCommand(addr);
    while (*String != '\0')
    {
        LCD_WriteData(*String);
        String++;
    }
}

void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    unsigned char buf[6];
    
    for(i=0; i<Length; i++)
    {
        buf[i] = Number % 10 + '0';
        Number /= 10;
    }
    
    for(i=Length; i>0; i--)
    {
        LCD_ShowChar(Line, Column + Length - i, buf[i-1]);
    }
}

void LCD_ShowChar(unsigned char Line, unsigned char Column, char Char)
{
    unsigned char addr;
    if (Line == 1)
        addr = 0x80 + (Column - 1);
    else
        addr = 0xC0 + (Column - 1);
    
    LCD_WriteCommand(addr);
    LCD_WriteData(Char);
}

最后是头文件区块:

===================================LCD1602.H===================================
#ifndef __LCD1602_H__
#define __LCD1602_H__

#include <reg52.h>

sbit LCD_RS = P1^2;
sbit LCD_RW = P1^1;
sbit LCD_EN = P1^0;
#define LCD_DATA_PORT P0


void LCD_Init(void);
void LCD_ShowChar(unsigned char Line, unsigned char Column, char Char);
void LCD_ShowString(unsigned char Line, unsigned char Column, char *String);
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length);
void LCD_Clear(void);

#endif

===================================DHT11.H===================================
#ifndef __DHT11_H__
#define __DHT11_H__

#include <reg52.h>

extern unsigned char DHT_Datas[5];

void Read_Data_From_DHT(void);

#endif

现在我们查看DHT11时序信号,也就是与主机对话的过程。

DHT11课程设计学习记录
DHT11课程设计学习记录
DHT11课程设计学习记录

代码片段解释:

void COM(void)
{
    unsigned char i;
    for (i = 0; i < 8; i++)//读取8位数据循环
    {
        U8FLAG = 2;
        while ((!dht) && U8FLAG++);//看门狗程序
        Delay_10us2();//延迟30us
        Delay_10us2();
        Delay_10us2();
        //54+27us等待判定电平
        U8temp = 0;//初始化数据
        if (dht) U8temp = 1;//写数据,如果0则为0,如果1则为1
        
        U8FLAG = 2;//重置看门狗
        while ((dht) && U8FLAG++);//看门狗数据递增
        if (U8FLAG == 1) break;//看门狗检查是否死循环
        
        U8comdata <<= 1;
        U8comdata |= U8temp;
    }
}
void Read_Data_From_DHT(void)
{
    EA = 0;//关闭中断
    
    dht = 0;
    Delay2(180);//延迟18ms
    dht = 1;//拉高电平
    //等待40us
    Delay_10us2();
    Delay_10us2();
    Delay_10us2();
    Delay_10us2();
    
    dht = 1;//由时序图,拉高后监测低电平输入
    
    if (!dht)如果是低电平进入循环
    {
        U8FLAG = 2;
        while ((!dht) && U8FLAG++);//看门狗
        
        U8FLAG = 2;
        while ((dht) && U8FLAG++);//看门狗
        
        COM();//读数据
        U8RH_data_H_temp = U8comdata;//写高位
        COM();
        U8RH_data_L_temp = U8comdata;//写低位
        COM();
        U8T_data_H_temp = U8comdata;//写高位
        COM();
        U8T_data_L_temp = U8comdata;//写低位
        COM();
        U8checkdata_temp = U8comdata; //写校验值
        
        dht = 1; //拉高总线等待下一次数据传送
        
        U8temp = (U8T_data_H_temp + U8T_data_L_temp + U8RH_data_H_temp + U8RH_data_L_temp);
        if (U8temp == U8checkdata_temp)//判断数据是否有误,如果无误,存入数组(内存)
        {

            DHT_Datas[0] = U8T_data_H_temp;
            DHT_Datas[1] = U8T_data_L_temp;
            DHT_Datas[2] = U8RH_data_H_temp;
            DHT_Datas[3] = U8RH_data_L_temp;
            DHT_Datas[4] = U8checkdata_temp;
        }
    }
    
    EA = 1;//恢复中断
}

接下来是LCD1602的困难函数解析:

void LCD_Init()//初始化函数
{
    delay_ms_proteus(20);   
    LCD_WriteCommand(0x38);//设置8位2行
    delay_ms_proteus(5);
    LCD_WriteCommand(0x0C);//开显示,关光标
    delay_ms_proteus(5);
    LCD_WriteCommand(0x06);//设置输入模式
    delay_ms_proteus(5);
    LCD_WriteCommand(0x01);//清屏
    delay_ms_proteus(5);
}
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    unsigned char buf[6];
    
    for(i=0; i<Length; i++)循环位数
    {
        buf[i] = Number % 10 + '0';//ASCII码获取
        Number /= 10;//取得下一组数
    }
    
    for(i=Length; i>0; i--)
    {
        LCD_ShowChar(Line, Column + Length - i, buf[i-1]);//正序显示
    }
}

最后是Proteus模拟电路图展示:

DHT11课程设计学习记录
- THE END -

BoxCat

12月22日15:56

最后修改:2025年12月22日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论