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
人不曾老去,直至悔恨取代了夢想!---約翰.巴裡摩