历史上的今天
返回首页

历史上的今天

今天是:2025年08月15日(星期五)

正在发生

2019年08月15日 | STM32读取温湿度传感器DHT11和DHT21(AM2301)系列问题

2019-08-15 来源:eefocus

1、DHT11和DHT21传感器


    这两种传感器都是奥松公司的产品,具体的传感器说明书在其官网上有(www.aosong.com)。


    DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数 字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一 个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。


    DHT21(AM2301)湿敏电容数字温湿度模块是一款含有己校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个高精度测温元件,并与一个高性能 8 位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在单片机中,传感器内部在检测信号的处理过程中要调用这些校准系数。标准单总线接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达 20 米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选择。产品为 3 引线(单总线接口)连接方便。特殊封装形式可根据用户需求而提供。


2、温湿度读取方式


    两种传感器均采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完 成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释 放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ的上拉电阻,这样,当总线闲置时, 其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须 严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。


3、两种传感器的主要区别


   包括两点,分别是单总线起始信号的数据总线拉低时间和温湿度高低位数据含义。


   DHT11的单总线格式定义:


   DHT21的单总线格式定义:

4、微秒级延时函数


    根据上面的介绍我们现在需要一个微秒级的精确延时函数,否则就不能成功的读取传感器数据。STM32单片机的滴答定时器可以满足。


  (1)保证滴答定时器的时钟频率为72MHz


    STM32F103内部8M的内部震荡,经过倍频后最高可以达到72M。在固件库3.0以上,只需要通过两步就可以完成对时钟频率的选择。


   ①修改system_stm32f10x.c开头的时钟宏定义,如下:


/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz  24000000 */ 

/* #define SYSCLK_FREQ_36MHz  36000000 */

/* #define SYSCLK_FREQ_48MHz  48000000 */

/* #define SYSCLK_FREQ_56MHz  56000000 */

#define SYSCLK_FREQ_72MHz  72000000

   ②在主函数main中调用SystemInit()函数。


   ③如果没有成功,需要检查单片机的晶振是否起振。简单的检测方法:


       有示波器的可以查看晶振的输出波形,正常应为正弦波。没有示波器的可以利用万用表分别测量晶振的管脚电平,正常应在1/2*VCC左右。


  (2)程序编写


    ①在main()函数中添加:SysTick_Config(72000000 / 1000000);//除以1000000微秒级(100000十微秒级,1000毫秒级),指进入中断的间隔时间


int main(void)

{      

    SystemInit();

    SysTick_Config(72000000 / 1000000);

}

    ②Delay.c


#include "stm32f10x.h"

#include "Delay.h"


int TimingDelay=0;


void delay_us(u32 n)

{

    TimingDelay=n;

  while(TimingDelay!=0); 

}

void delay_ms(u32 n)

{

    while(n--)

    {

     delay_us(1000);        

    }

}

      Delay.h


#ifndef _DELAY__H_

#define _DELAY__H_


void delay_us(u32 n);

void delay_ms(u32 n);


#endif

    ③stm32f10x_it.c


extern int TimingDelay;

void SysTick_Handler(void)

{

    if(TimingDelay!=0)

    {

        TimingDelay--;    

    }

}

5、编写读传感器数据程序


    ①DHxx.c


#include "stm32f10x.h"

#include "DHxx.h"

#include "Delay.h"

#include "sys.h"

u8 tdata[4]={0x00,0x00,0x00,0x00};

u8 sbuf,check;


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

//      //uchar       i;

//      uchar    U8FLAG,k;

//      uchar    U8count,U8temp;

//      uchar    U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;

//      uchar    U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;

//      uchar    U8comdata;

//      uint   ReceiveHighByte;

//      uint   ReceiveLowByte;

//***************Global defination for DHT11 end****// 

void DHT_PortIN(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     

    GPIO_Init(GPIOB,&GPIO_InitStructure);

}

void DHT_PortOUT(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     

    GPIO_Init(GPIOB,&GPIO_InitStructure);

}

unsigned char StartDHT11(void)

{

   DHT_PortOUT();

   DHT_Out = 0;

   delay_ms(20);  //DHT11>18ms

  

   DHT_Out = 1;    

     DHT_PortIN();

   delay_us(20);  


   if(!DHT_In)

   {

           while(!DHT_In);

           while(DHT_In);

           return 1;

   }

    return 0;

}


unsigned char StartDHT21(void)

{

   DHT_PortOUT();

   DHT_Out = 0;

   delay_ms(1);  //DHT21>800us

  

   DHT_Out = 1;

     DHT_PortIN();

   delay_us(20);  


   if(!DHT_In)

   {

            while(!DHT_In);

           while(DHT_In);

           return 1;

   }

    return 0;

}

void com(void)

{

    u8 i,tt;

    tt = 0;

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

    {

        sbuf <<= 1;

        delay_us(20);

        while(!DHT_In);

        delay_us(25);

        tt = 100;

        while(tt++);

        if(DHT_In)

        {

             sbuf |= 0x01;

             delay_us(30);

        }

        else

        {

            sbuf &= 0xfe;

        }

    }

}

u8 ReadDHT11(void)

{

    u8 sum;

    if(StartDHT11())    

    {

        com();

        tdata[0]=sbuf;

        com();

        tdata[1]=sbuf;

        com();

        tdata[2]=sbuf;        

        com();

        tdata[3]=sbuf;

        com();

        check = sbuf;

        sum = (tdata[0]+tdata[1]+tdata[2]+tdata[3]);

    }

    if(check == sum)

    return(1);

    else    

    return 0;

}


u8 ReadDHT21(void)

{

    u8 sum;

    if(StartDHT21())    

    {

        com();

        tdata[0]=sbuf;

        com();

        tdata[1]=sbuf;

        com();

        tdata[2]=sbuf;        

        com();

        tdata[3]=sbuf;

        com();

        check = sbuf;

        sum = (tdata[0]+tdata[1]+tdata[2]+tdata[3]);

    }

    if(check == sum)

    return(1);

    else    

    return 0;

}

    DHxx.h                     //(注意:我这边定义的DATA管脚为PB1)


#ifndef _DHXX__H_

#define _DHXX__H

#include "sys.h"

#define DHT_Out PBout(1)

#define DHT_In  PBin(1)


#define uchar unsigned char 

#define uint  unsigned int


unsigned char StartDHT11(void);

unsigned char StartDHT21(void);

void DHT_PortIN(void);

void DHT_PortOUT(void);

u8 ReadDHT11(void);

u8 ReadDHT21(void);

void com(void);

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


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


extern u8 tdata[4];

extern u8 sbuf;

extern u8 check;


#endif

    ②sys.h


#include "stm32f10x.h"


///////////////////////////////////////////////////////////////

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 

#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 

#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

//IO地址映射

#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 

#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 

#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 

#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 

#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 

#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    

#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    


#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 

#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 

#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 

#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 

#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 

#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 

#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 

 

//IO口操作,只针对单一的IO口//n的值小于16

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出

#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入


#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  

#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  


#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n) 

#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  


#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n) 

#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n) 


#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  

#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  


#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  

#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  

推荐阅读

史海拾趣

Amphenol Thermometrics公司的发展小趣事

Amphenol Thermometrics 是 Amphenol 公司旗下的子公司,专注于设计、制造和销售温度传感器和测量解决方案,在电子行业和其他领域发挥着重要作用。以下是关于 Amphenol Thermometrics 公司发展的五个相关故事:

  1. 创立与初期发展:Amphenol Thermometrics 公司的历史可以追溯到20世纪60年代,当时公司成立于美国纽约州的克拉克森市。最初,公司主要致力于生产温度传感器和测量装置,为不同行业的客户提供可靠的温度监测解决方案。随着技术的进步和市场需求的增长,Amphenol Thermometrics 逐渐壮大成为温度传感器领域的重要参与者。

  2. 技术创新与产品多样化:Amphenol Thermometrics 公司在温度传感器领域持续进行技术创新,并不断推出新型的温度传感器和测量解决方案。公司致力于提升产品的精度、灵敏度和可靠性,满足客户对高性能温度监测设备的需求。除了传统的温度传感器,Amphenol Thermometrics 还推出了一系列新型产品,如热电阻、热敏电阻、红外线传感器等,拓展了产品线的多样性。

  3. 客户合作与定制化解决方案:Amphenol Thermometrics 公司与客户建立了密切的合作关系,共同开发定制化的温度传感器和测量解决方案。公司的工程团队与客户紧密合作,根据客户的需求和应用场景,设计和制造符合特定要求的产品。这种定制化解决方案能够满足客户个性化的需求,为客户提供更加专业和完善的温度监测服务。

  4. 质量控制与认证标准:Amphenol Thermometrics 公司高度重视产品质量控制,并严格遵循国际质量管理体系标准。公司的生产工艺和质量管理体系符合ISO 9001质量管理体系认证标准,以确保产品质量的稳定性和可靠性。此外,Amphenol Thermometrics 公司的产品还通过了各种行业和应用领域的认证标准,如汽车行业的TS16949认证等,确保产品符合行业标准和规定。

  5. 全球市场拓展与合作伙伴关系:除了在美国的生产基地外,Amphenol Thermometrics 公司还在全球范围内设有多个销售办事处和代理商网络,拓展了国际市场份额。公司与全球各种行业领先企业建立了长期稳定的合作关系,共同推动产品的创新和市场拓展。通过全球市场拓展和合作伙伴关系,Amphenol Thermometrics 公司不断扩大业务规模,增强了在温度传感器领域的市场竞争力。

这些故事展示了 Amphenol Thermometrics 公司从成立初期到如今在技术创新、产品多样化、客户合作与定制化解决方案、质量控制与认证标准以及全球市场拓展与合作伙伴关系等方面取得的重要进展。

迈翔科技(COILMX)公司的发展小趣事

进入21世纪后,迈翔科技面临了来自国内外同行的激烈竞争。为了保持竞争力,公司投入大量资源进行技术研发和创新。通过不懈努力,公司成功开发出了一系列高性能的贴片功率电感和大电流电感,这些产品凭借卓越的性能和稳定的品质,迅速获得了市场的认可。

台湾晶豪(ESMT)公司的发展小趣事

随着电子行业的不断发展,晶豪科技也积极应对市场变化。公司扩大代工厂的晶圆开工规模,以满足不断增长的客户需求。这一举措不仅使公司能够更灵活地应对市场波动,还为客户提供了更稳定的产品供应。同时,随着晶圆开工量的增加,公司的销售额也实现了稳步增长。

Anders DX公司的发展小趣事

晶豪科技(ESMT)于1998年由赵瑚博士创立,公司自初创时就立志成为客户各类型内存产品及技术的供应者。经过数年的努力,公司在DRAM产品研发上取得了显著成果,广泛应用于PC外围、信息家电、消费性电子产品及通讯系统等领域。2002年3月,晶豪科技在台湾证券交易所成功挂牌上市(代号3006),这一里程碑事件为公司后续的发展奠定了坚实基础。

Analog Power公司的发展小趣事

Analog Power公司成立于XXXX年,创立初期主要专注于电源管理解决方案的研发。面对当时竞争激烈的市场环境,公司创始人凭借对电源管理技术的深刻理解和坚定信念,带领团队克服了种种困难,逐步在市场中找到了自己的定位。他们深入研究客户需求,不断优化产品设计,逐渐赢得了客户的信任和认可。

EXCELSEMI [ EXCEL SEMICONDUCTOR INC. ]公司的发展小趣事

为了满足不同客户的需求,EXCELSEMI公司不断扩展产品线。除了传统的半导体芯片产品外,公司还涉足了功率半导体、传感器、智能模块等领域。通过多元化的产品线布局,EXCELSEMI能够为客户提供一站式解决方案,增强了市场竞争力。

问答坊 | AI 解惑

可控硅应用中的十条黄金原则

还不错,好东西就是要和大家共享…

查看全部问答>

电子门禁系统有辐射吗?

最近宿舍楼里装了门禁系统,要刷卡进入。但是是那种仅容一人通过的两面有栏版的东西,一过人就响。这是不是有辐射呢?每天要过好几回。…

查看全部问答>

我电脑的串口很神经.

来自EEWORLD合作群:arm linux fpga 嵌入0(49900581) 群主:wangkj 用着用着 就只能收, 不能发. 重启一下电脑就好了. 各位大神 , 可能是哪方面的原因?…

查看全部问答>

转帖,免费的开发板及资料

第二次免费开发板赠送,40mb 开发资料包:实例,原理图,keil 正式版,免费下载 第二次免费开发板赠送,40mb 开发资料包:实例,原理图,keil 正式版,免费下载 下载50个单片机程序实例和开发板原理图,学林电子免费开发板暑期助学活动报名!暑假在家 ...…

查看全部问答>

软件工程贴吧

渥瑞达\"3G移动开发\"免费试听课于北京交通大学举行,欢迎大家光临! 详情请参见 www.neworigin.net 同时欢迎大家与我们的609期学员交流!这期学员已与2月11日毕业。 学员就业薪水都在5000元/月以上 您还可以加入渥瑞达学员的QQ群与学员面对面 ...…

查看全部问答>

我的串口读不到数据.net程序

public void Open()                         {                                 //Init_Com ...…

查看全部问答>

STM32FLASH读保护测试,片子挂了,高手帮忙请进!

你必须写一个程序并使用JTAG在RAM中运行,这个程序的目的是清除Flash的读写保护,这样Flash的内容会自动被擦除,然后Flash就可以重新使用了。下次做这样的操作时,请预置一段清除Flash的读写保护的程序,这段程序能够通过某种机制启动,这样就 ...…

查看全部问答>

STM8S外部中断的问题

                                 请问STM8S进了外部中断以后如何清中断标志位?好像参考手册没有讲…

查看全部问答>

赠送一枚TI eStore 8折优惠码

可以购买: MSP430 Capacitive Touch Bundle,MSP430 Capacitive Touch BoosterPack,MSP430 USB Debugging Interface,MSP430 USB Stick Development Tool , MSP-EXP430FR5739 Experimenter Board ,MSP430F5438 Experimenter Board 有效期至 ...…

查看全部问答>