历史上的今天
返回首页

历史上的今天

今天是:2025年10月11日(星期六)

正在发生

2022年10月11日 | 51单片机基础之DHT11温湿度传感器

2022-10-11 来源:csdn

接线: 

代码:


main.c文件

 

/*

使用DHT11模块,检测温湿度,在lcd1602上面显示,因为1602显示不是每次都能出来,所以加了串口打印,会更加直观。

*/

#include

#include "lcd.h"

#include

#include

 

sbit Temp_data=P3^6; //信号引脚

 

unsigned int rec_dat[4];

unsigned char rec_dat_lcd0[6];

unsigned char rec_dat_lcd1[6];

unsigned char rec_dat_lcd2[6];

unsigned char rec_dat_lcd3[6];

 

void DHT11_delay_us(unsigned char n);

void DHT11_delay_ms(unsigned int z);

void DHT11_start();

unsigned char DHT11_rec_byte();

void DHT11_receive();

void InitUART(void);

 

//主函数

void main()

{

InitUART(); //串口中断初始化

P1=0xf0;

InitLcd1602();

LcdShowStr(0,0,"Shidu:");

LcdShowStr(0,1,"Wendu:");

 

while(1)

{

DHT11_delay_ms(150);

DHT11_receive();

 

//这个函数是打印字符函数,应该是起到数值转化的作用。

sprintf(rec_dat_lcd0,"%d",rec_dat[0]);

sprintf(rec_dat_lcd1,"%d",rec_dat[1]);

sprintf(rec_dat_lcd2,"%d",rec_dat[2]);

sprintf(rec_dat_lcd3,"%d",rec_dat[3]);

DHT11_delay_ms(100);

//湿度

LcdShowStr(7,0,rec_dat_lcd0);

LcdShowStr(9,0,".");

LcdShowStr(10,0,rec_dat_lcd1);

LcdShowStr(11,0," %");

//温度

LcdShowStr(7,1,rec_dat_lcd2);

LcdShowStr(9,1,".");

LcdShowStr(10,1,rec_dat_lcd3);

LcdShowStr(11,1," C");

//下面通过串口助手打印温度

//我也为什么他不用中断服务函数,就可以打印,那好需要这个中断干嘛,不是可以直接打印吗?这是我的疑问。

printf("Humi:%d.%d n",rec_dat[0],rec_dat[1]);

printf("Temp:%d.%d °Cn",rec_dat[2],rec_dat[3]);

}

}

 

//DHT11起始信号

void DHT11_start()

{

Temp_data=1;

DHT11_delay_us(2);

Temp_data=0;

DHT11_delay_ms(20);

Temp_data=1;

DHT11_delay_us(13);

}

 

//接收一个字节

unsigned char DHT11_rec_byte()

{

unsigned char i,dat;

for(i=0;i<8;i++)

{

while(!Temp_data);

  DHT11_delay_us(8);

dat<<=1;

if(Temp_data==1)

{

dat+=1;

}

while(Temp_data);

}

return dat;

}

 

//接收温湿度数据

void DHT11_receive()

{

unsigned int R_H,R_L,T_H,T_L;

unsigned char RH,RL,TH,TL,revise;

DHT11_start();

Temp_data=1;

if(Temp_data==0)

{

while(Temp_data==0);   //等待拉高     

        DHT11_delay_us(40);  //拉高后延时80us

        R_H=DHT11_rec_byte();    //接收湿度高八位  

        R_L=DHT11_rec_byte();    //接收湿度低八位  

        T_H=DHT11_rec_byte();    //接收温度高八位  

        T_L=DHT11_rec_byte();    //接收温度低八位

        revise=DHT11_rec_byte(); //接收校正位

 

        DHT11_delay_us(25);    //结束

 

        if((R_H+R_L+T_H+T_L)==revise)      //校正

        {

            RH=R_H;

            RL=R_L;

            TH=T_H;

            TL=T_L;

        } 

        /*数据处理,方便显示*/

        rec_dat[0]=RH;

        rec_dat[1]=RL;

        rec_dat[2]=TH;

        rec_dat[3]=TL;

}

}

//延时us   --2*n+5us

void DHT11_delay_us(unsigned char n)

{

    while(--n);

}

 

//延时ms

void DHT11_delay_ms(unsigned int z)

{

   unsigned int i,j;

   for(i=z;i>0;i--)

      for(j=110;j>0;j--);

}

 

//使用定时器1作为串口波特率发生器

void InitUART(void)

{

TMOD=0x20; //定时器1的工作方式2

SCON=0x40; //串口通信工作方式1

REN=1; //允许接收

TH1=0xFD,TL1=0xFD; //波特率=9600

TI=1;                       //这里一定要注意

TR1=1;

EA = 1;                  //开总中断

}


Lcd.c文件

 

#include"lcd.h"

 

void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令

{

    //Read_Busy();

    LCD1602_RS = 0;

    LCD1602_RW = 0;

    LCD1602_DB = cmd;

LCD_Delay10ms(1);

    LCD1602_EN = 1;

LCD_Delay10ms(1);

    LCD1602_EN = 0;    

}

 

void Lcd1602_Write_Data(unsigned char dat)   //写数据

{

      //Read_Busy();

      LCD1602_RS = 1;

      LCD1602_RW = 0;

      LCD1602_DB = dat;

LCD_Delay10ms(1);

      LCD1602_EN = 1;

LCD_Delay10ms(1);

      LCD1602_EN = 0;

}

//指定位置开始显示数据!

void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示

{

    unsigned char addr;

    if(y == 0)

        addr = 0x00 + x;//第一行开始,x表示一行的第x个

    else

        addr = 0x40 + x;//第二行开始,x表示一行的第x个

    

    Lcd1602_Write_Cmd(addr|0x80);

}

 

void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串

{

    LcdSetCursor(x,y);      //当前字符的坐标

    while(*str != '')

    {

        Lcd1602_Write_Data(*str++);

    }

}

 

void InitLcd1602()              //1602初始化

{

    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据

    Lcd1602_Write_Cmd(0x0c);

    Lcd1602_Write_Cmd(0x06);

    Lcd1602_Write_Cmd(0x01);    //清屏   

}

 

void LCD_Delay10ms(unsigned int c)   //误差 0us

{

    unsigned char a,b;

    for(;c>0;c--)

        for(b=38;b>0;b--)

            for(a=130;a>0;a--);

}


Lcd.h文件

 

#ifndef __LCD_H_

#define __LCD_H_

/**********************************

当使用的是4位数据传输的时候定义,

使用8位取消这个定义

**********************************/

//#define LCD1602_4PINS

/**********************************

包含头文件

**********************************/

#include

//---重定义关键词---//

#ifndef uchar

#define uchar unsigned char

#endif

#ifndef uint 

#define uint unsigned int

#endif

/**********************************

PIN口定义

**********************************/

#define LCD1602_DB  P0      //data bus 数据总线

sbit LCD1602_RS = P2^6;

sbit LCD1602_RW = P2^5;

sbit LCD1602_EN = P2^7;  

/**********************************

函数声明

**********************************/

/*在51单片机12MHZ时钟下的延时函数*/

//void Lcd1602_Delay1ms(uint c);   //误差 0usvo

void LCD_Delay10ms(unsigned int c);

//void Read_Busy();           //忙检测函数,判断bit7是0,允许执行;1禁止

void Lcd1602_Write_Cmd(unsigned char cmd);     //写命令

void Lcd1602_Write_Data(unsigned char dat);   //写数据

void LcdSetCursor(unsigned char x,unsigned char y);  //坐标显示

void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);     //显示字符串

void InitLcd1602();              //1602初始化

  

#endif


运行结果:

 

推荐阅读

史海拾趣

Amecon Magnetics公司的发展小趣事

随着电子行业的快速发展,对高性能磁性材料的需求日益增长。Amecon Magnetics公司敏锐地捕捉到这一市场机遇,加大了在技术研发上的投入。通过不断的技术创新,公司成功开发出一系列具有高性能、高稳定性的磁性材料产品,满足了市场对于高质量磁性材料的需求,从而赢得了客户的信任和市场的认可。

比亚迪(BYD)公司的发展小趣事

进入21世纪,新能源汽车市场逐渐兴起。比亚迪凭借在电池领域的深厚积累,果断转型进入新能源汽车领域。2000年,比亚迪推出了全球第一款纯电动乘用车——比亚迪e6,这一创新产品引起了市场的广泛关注。此后,比亚迪不断加大对新能源汽车的研发和生产投入,推出了多款具有竞争力的新能源汽车产品。同时,比亚迪还积极涉足光伏和LED照明等其他领域,不断拓展其电子业务版图。

CR Magnetics公司的发展小趣事

CR Magnetics公司成立于1986年,自创立之初,公司便致力于提供高质量的传感器、传感器组件等系列产品。凭借创始人的远见卓识和团队的共同努力,CR Magnetics很快在电子行业中崭露头角。公司总部位于美国密苏里州圣路易斯市,拥有先进的生产设施和仓库,为产品的研发和生产提供了坚实的基础。

Datakey Electronics公司的发展小趣事

随着全球化进程的加速,Datakey Electronics意识到单靠国内市场已经无法满足公司的长远发展需求。于是,公司积极寻求国际合作机会,与国际知名企业建立战略合作伙伴关系,共同开发新产品、开拓新市场。通过国际合作,Datakey Electronics不仅提高了自身的技术水平和产品竞争力,还成功将产品推向了国际市场。

Curtis Industries公司的发展小趣事

随着电子行业的不断发展,Curtis Industries公司意识到技术创新的重要性。公司投入大量资源进行技术研发,成功推出了一系列具有行业领先水平的产品。其中,公司在某一关键领域的突破性技术,不仅解决了行业内的技术难题,还为公司赢得了广泛的赞誉。Curtis Industries因此成为了电子行业的技术创新引领者,推动了整个行业的发展。

Cynergy 3公司的发展小趣事

为了进一步扩大市场份额,Cynergy 3制定了国际化发展战略。公司积极参加国际展会和会议,与全球各地的客户和合作伙伴建立联系。同时,Cynergy 3还在全球范围内设立了多个分支机构和服务中心,以便更好地为客户提供服务。这些努力使得Cynergy 3的产品逐渐进入了国际市场,并赢得了众多国际客户的青睐。

问答坊 | AI 解惑

一个嵌入式开发的资料(希望抛砖引玉)

嵌入式的开发如今是变的越来越复杂,对嵌入式工程师的要求越来越高。如何从一个应届毕业生, 或者普通的工程师向嵌入式迈进呢。网络上的资料很多,书店的书籍也很多,但大家都很难下手或者靠自学提高。 在最近的公司招聘面试的过程中,发现很多面试者( ...…

查看全部问答>

LCD501液晶屏电子钟和电压表程序

本帖最后由 paulhyde 于 2014-9-15 08:57 编辑 见附件  …

查看全部问答>

TMS320C6713DSP地址线问题

TMS320C6713DSP 地址线是20根吗?为什么它的标号是从EA2开始?(其地址标号为EA2-EA21) datasheet中所说的每个CE可选择128MB空间是怎么算出来的? 先谢谢您的答复!…

查看全部问答>

请问没有系统的UART编程和CE下的UART编程的区别?

撇开软件部分不说,单看硬件方面的设置: 1)基于ARM7裸机的串口简单的编程:如串口初始化,设置波特率,寄存器设置,中断向量设置等 2)自己基于CE下编一个串口驱动,也是要向上面一样设置ARM芯片的初始化吗?和裸机的那些设置是一样 ...…

查看全部问答>

求救,按键驱动

现在我想写一个2440的按键驱动,只需要几个按键就可以了,比较(上,下,左,右功能)。 要求能够传递给任意进程中,比如按上下左右键能够操作控制界面(UI)。 请问是不是只能在提供的标准的键盘驱动中写,有没有更简单的方法,哪位大哥给点思路呀…

查看全部问答>

ATMEGA8--想要爱你不容易!!

      在这夏天,炎热酷暑。在这夏天,躲在架设有几十台电脑的实验室,狭窄的空间,空气是凝固的,室内气温自然上去了。就这样,度过了一个刻骨铭心的暑假!然而,一个暑假下来,付出是多,收获也是多的。你们是否记得, ...…

查看全部问答>

高品质LED产品指标性能

replyreload += \',\' + 756734;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

IAR使用J-Link仿真的问题

我写了一个LM3S9B92的UART简单收发程序,想下载到开发板中,用的是IAR软件,和J-LINK仿真器,请高手指教一下具体的步骤,比如说软件的相关配置等等问题,谢了   我在下载的 过程中出现了这个问题 Fatal Error[Lc002]: could not open file ...…

查看全部问答>

STM32的页擦除的擦除范围

页擦除 闪存的任何一页都可以通过FPEC的页擦除功能擦除;擦除一页应遵守下述过程: 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作; 设置FLASH_CR寄存器的PER位为’1’; 用FLASH_AR寄存器选择要擦除的页; 设置FLASH_C ...…

查看全部问答>

关于自适应相干模板法的问题

小弟接触单片机编程不到一年,最近在尝试用自适应相干模板法做50HZ工频干扰信号的数字陷波器,照着《自适应相干模板法在5 1系列单片机中的实现》里的算法写了C代码,用430运行后发现,不管输入什么频率的信号,输出都差不多,就是一串奇怪的方波, ...…

查看全部问答>