历史上的今天
返回首页

历史上的今天

今天是:2025年08月14日(星期四)

正在发生

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

2019-08-14 来源: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)  

推荐阅读

史海拾趣

Capax Technologies Inc公司的发展小趣事

Capax Technologies Inc的崛起始于一次技术突破。公司研发团队成功开发出一种新型半导体材料,显著提高了电子设备的性能和能效。这一创新成果迅速在行业内引起关注,Capax Technologies Inc因此获得了大量订单和投资。随着技术的不断迭代和优化,Capax Technologies Inc逐渐在电子行业中崭露头角,成为一家备受瞩目的创新型企业。

Anritsu公司的发展小趣事

随着国内市场的饱和,Capax Technologies Inc开始积极拓展海外市场。公司制定了详细的国际化战略,通过设立海外研发中心、建立销售网络等方式,逐步进入国际市场。在国际化的过程中,Capax Technologies Inc不仅提升了自身的技术水平和市场竞争力,还积累了丰富的国际经验,为公司的长远发展奠定了坚实基础。

芯联(CHIPLINK)公司的发展小趣事

芯联集成非常重视企业文化建设,致力于打造一个高效、协作、创新的团队。公司倡导“以人为本”的管理理念,关注员工成长和发展,为员工提供良好的工作环境和福利待遇。同时,公司还建立了完善的激励机制和培训体系,激发员工的工作热情和创造力。这些努力使芯联集成在行业内树立了良好的口碑和形象,吸引了众多优秀人才加入公司。

Harbour Industries公司的发展小趣事

背景:20世纪末,随着电子技术的飞速发展,Handok敏锐地捕捉到了半导体行业的崛起机遇。公司决定投入大量研发资源,专注于开发新型半导体材料和技术。

发展:经过数年的潜心研究,Handok成功研发出一种具有更高导电性和稳定性的新型半导体材料,这一创新成果迅速获得了业界的广泛关注。公司迅速将这项技术应用于生产,推出了一系列高性能的半导体产品,迅速占领了市场的一席之地。

影响:Handok的技术革新不仅推动了公司自身的快速发展,还对整个半导体行业产生了深远的影响,促进了整个产业链的升级和转型。

EFINIX公司的发展小趣事

为了加速Quantum™可编程加速器技术的商业化进程,EFINIX公司与中芯国际集成电路制造有限公司展开合作。中芯国际是世界领先的集成电路晶圆代工企业之一,其先进的制造能力为EFINIX公司提供了强有力的支持。双方合作仅用了不到六个月的时间,就成功交付了首批Quantum™可编程加速器产品样本,创造了行业内的里程碑。

ACT [Advanced Crystal Technology]公司的发展小趣事

EFINIX公司继续深化其在FPGA领域的技术创新,成功推出了Trion FPGA产品系列。该产品具有低功耗、精细封装面积和强大的性能特点,深受市场欢迎。在Trion FPGA产品销售的头三个月里,EFINIX公司获得了多项设计认可和客户订单,并有很多客户已经开始使用Trion FPGA进行产品设计。

问答坊 | AI 解惑

PCB地与地的问题

一块PCB板子的地与接插件的地不通会怎样?怎样才会不通?各位大大99…

查看全部问答>

基于KEELOQ跳码技术的密码发生器设计

基于密码的访问控制系统应用在当今是非常普遍的,但人们对其提供的安全等级经常估计过高。通信传输速度和系统计算能力的提高使得系统受到恶意攻击或“密码扫描”的风险增加。在使用不安全的传送方式时,可能发生密码被盗取的现象。例如典型的通过电 ...…

查看全部问答>

求教:功耗问题

    我用的是飞思卡尔的射频芯片MC13213,需要完成的功能是:用MC13213的I2C接口接收数据,当从机有中断信号的时侯开始接收数据,接收到的数据不为0时才通过射频发送数据。    可是在功耗上出现了问题:不管有没有中断产生, ...…

查看全部问答>

添加记录问题

Imports System.Data.SqlServerCe Imports System.IO Public Class Form2     Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load        &nbs ...…

查看全部问答>

RELEASETYPE is not set. Using default settings.

今天编译CE5.0内核遇到这么个警告: RELEASETYPE is not set. Using default settings. 结果导致编译出错,而用同样的BSP在我同事的机子上却没事,所以我怀疑是PB出了问题,哪位大侠给指点一下…

查看全部问答>

AVR中怎么象51那样把不变的数据存到代码段?

最近 做东西需要很多数据的存储但是空间有限啊就是要把一些不变的制度数据存到其他的地方中去,以免占用太多的数据存储空间。。…

查看全部问答>

Nand Flash 分区只得到一半的容量?

wince5.0 下 flash是 1G bytes 的,型号K9K8G08U0M 分号区后,我在存储管理器中看到,容量:960M,未分配的:896M,我只分到64M. 问题: 1、怎样我才能将未分配的容量加分出来呢? 2、OS是通过哪个函数分得64M的呢,FMD_ReadSector()?我驱 ...…

查看全部问答>

创意盲文手机:接通的不仅仅是电话

创意盲文电话:接通的不仅仅是电话最近热播的中国移动最新广告,打动了无数人的情绪,就像安静水面掉入的一个小石块,激起层层涟漪,让我们的内心久久不能安静,这样的创意应当受到感谢的掌声。同样,这款创意盲文手机,也是一个巨大的创意,也许它 ...…

查看全部问答>

AT89C51控制M62429的程序谁有?

AT89C51控制M62429程序中的发送6位数据和发送5位数据子程序我不会作,谁能教教我?…

查看全部问答>

求助!ccs与目标板连接连接不上

我自己做了一块dsp28016的最小系统,测得电压、时钟信号都是正常的,用的仿真器是spectrum digital 510LC usb 每次连接报错是: Error connecting to the target: Error 0x80000200/-1135 Fatal Error during: OCS, Unrecoverable emulation ...…

查看全部问答>