STM32讀取溫濕度感測器DHT11和DHT21(AM2301)系列問題

来源:https://www.cnblogs.com/lemonzhang/archive/2018/04/07/8732658.html
-Advertisement-
Play Games

1、DHT11和DHT21感測器 這兩種感測器都是奧松公司的產品,具體的感測器說明書在其官網上有(www.aosong.com)。 DHT11 數字溫濕度感測器是一款含有已校準數字信號輸出的溫濕度複合感測器。它應用專用的數 字模塊採集技術和溫濕度感測技術,確保產品具有枀高的可靠性與卓越的長期穩定性。 ...


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>80us
  
   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) #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) /////////////////////////////////////////////////////////////////

    ③main.c

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include "system.h"
#include "sys.h"
#include "DHxx.h"
#include "Delay.h"
int main(void)
{      
    SystemInit();
    SysTick_Config(72000000 / 1000000);
    while(1)
    {
        ReadDHT11();// ReadDHT21();//讀取的信息在DHxx.c的tdata[]數組中
        delay_ms(1000);
        delay_ms(1000);  //註意讀取間隔應該在2秒以上 
        }
}    

6、參考

【1】單片機stm32時鐘頻率 http://www.elecfans.com/dianzichangshi/20171113578546.html

【2】https://wenku.baidu.com/view/6306fbf484254b35eefd3428.html

【3】http://www.aosong.com/products-28.html

  

人不曾老去,直至悔恨取代了夢想!---約翰.巴裡摩

 

     

     

    

     

      

 

 

   

 

   


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 做為一個碼農,對新技術的學習是必須滴,但是在學習的同時也要記錄下筆記。讓子彈飛的一句話“步子邁大了容易扯著dan” 話糙理不糙。這句感覺很貼切我們的碼農。 真正做開發滿打滿算有4年了。其中兩年的時間幾乎就像流水線工人的工作,每天也就是改改bug,寫寫存儲過程,當時的存儲過程是信手拈來,一些臨時表、游 ...
  • 首先要明確什麼是中間件?微軟官方解釋:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?tabs=aspnetcore2x 也就是中,我們需要在整個應用程式的請求管道中註入某一個中間層來做我們想做的事情。談談我 ...
  • 一、前言 1.Vagrant是一個搭建完整的虛擬開發環境的工具~~~更多關於Vagrant理論可查看這篇博文https://www.cnblogs.com/davenkin/p/vagrant-virtualbox.html 2.實驗環境 在Win10中利用VMWare Workstation創建一 ...
  • 一、安裝遠程伺服器管理工具: 下載地址: https://www.microsoft.com/zh-cn/download/details.aspx?id=45520 二、關閉遠程伺服器管理工具: 1 在桌面上右擊“開始”,進入“程式和功能” 2 單擊程式,然後在程式和功能中單擊“啟用或關閉 Win ...
  • 系統版本:安裝依賴:由於RabbitMQ依賴Erlang, 所以需要先安裝Erlang。Erlang的安裝方式大概有兩種:(1) Erlang Solution安裝(推薦)wget https://packages.erlang-solutions.com/erlang-solutions-1.0-... ...
  • 上周剛入手了2017版MacBookPro,預裝macOS High Sierra。第一次接觸Mac系統,經過一周的使用,簡單總結下與Windows相比最常用的功能,快速上手。 1、Mac鍵盤實現Home、End、Page UP、Page DOWN這幾個鍵 macbookpro鍵盤沒有Home、En ...
  • 需求:和老婆一起玩雙人同屏游戲(以撒的結合:抗生),但需要帶上藍牙耳機玩。 設備:2個藍牙耳機、1個藍牙接收器、1台Win10系統電腦。 通過關鍵字搜索出一個解決方案(Output audio to multiple devices in Windows 10) 在我電腦上測試無法實現。 但順著思路 ...
  • 《unix環境高級編程·第三版》源代碼編譯及使用 《unix環境高級編程》中有很多示例代碼需要包含作者自定義的頭文件,如"apue.h"。這些代碼可以從以下網址下載 http://apuebook.com/code3e.html 1. 解壓文件 2. 安裝 ,否則編譯會報錯不通過,會提示編譯thre ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...