|
1.DHT11简介 DHT11是一款温湿度一体化的数字传感器,该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机连接。通过单片机微处理器简单的电路连接就能够实时的采集湿度和温度。DHT11与STM32之间能采用简单的单总线进行通讯,仅需一个IO口。传感器内部温度和湿度数据40个bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。 DHT11采用单总线数据格式,即单个数据引脚端口完成输入输出双向传输。其数据包由5个字节(40Bit)组成。数据分小数和整数部分,一次完整的数据传输为40bit,高位先出。数据格式如下图示
1 j- m3 j9 v1 f# P3 t
- [" i% a `8 K) A( U# W9 Q9 Y
根据以上数据,即可算出温度和湿度的值,计算方法如下: 湿度 = byte4.byte3 温度 = byte2.byte1 校验 = byte4 + byte3 + byte2 + byte1 , T/ F& O, n/ j
DHT11和单片机的一次通讯最大为3ms左右,建议主机连续读取时间间隔不要小于100ms,下面是DHT11的三种时序:
6 w" g- h: ]6 P$ q: \3 E/ W
⏩ 数据发送时序 首先主机发送开始信号,即拉低数据线保持t1(至少18ms)时间,接着拉高数据线t2(20 ~ 40us)时间;然后读取DHT11的响应,正常的话DHT11会拉低数据线并保持t3(40 ~ 50us)时间作为响应信号,接着DHT11拉高数据线并保持t4(40 ~ 50us)时间后,开始传输数据
* r6 N4 w# U% |$ a8 `1 j
?. D% }* n- q4 E' w$ s
⏩ DHT11输出0时序
3 W% Y0 F8 ~* E3 Z0 r% J H7 s
: o$ T/ \: h( \! o8 A n
⏩ DHT11输出1时序
7 Z, v2 L a+ L+ Y
1 X9 V- I; k' Q" Z0 V
& Z7 Y1 s' F' U0 y2.硬件设计 0 y# V4 T" [/ i' K6 k- p
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值 指示灯D1 USART1串口 PG11 TIM7(提供us延时)
! d7 x7 F9 R/ W- }/ O: D
8 V# v1 N; h5 V3.软件设计 3.1 STM32CubeMX设置
9 B! c f9 [& [, O( B
➡️ RCC设置外接HSE,时钟设置为72M
8 B/ M8 y/ {% k! x7 ~: I' i
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
+ [3 o) F3 C% f- H" M& X
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位 ) ]( I e+ A5 }$ W) a1 ?
➡️ PG11设置为GPIO推挽输出模式、上拉、高速
! N2 f W) x& U# P5 I* H+ \
➡️ 激活TIM7,预分频因子设为72-1,向上计数,自动重载值为65535;因此计数器CNT_CLK = 1MHz,计数器周期为1us
- D8 E& q( n; o3 h8 r
& {: t- ^3 Z! Y. @/ T! [9 \0 u
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码 - _* e, w/ k; C% T4 h- N
3.2 MDK-ARM软件编程
' x! K! _" S7 z1 Y$ A" C* L( ~
➡️ 在tim.c文件下实现微秒延时(us)函数 - void delay_us(uint16_t us){
. |1 z6 D1 W: x: {; Q/ j - uint16_t differ = 0xffff-us-5;
% B; w5 P% `# [* B# X3 [ - //设定TIM7计数器起始值 " F8 D# z6 `: S2 R& S3 _- d
- __HAL_TIM_SET_COUNTER(&htim7,differ);
+ a+ U6 {( X* H% b" O& X - //启动定时器 . A% _ i5 K1 k' U" R3 f+ l2 x
- HAL_TIM_Base_Start(&htim7); 2 g( \7 z9 f( @7 g* c5 ~5 j
-
% x6 v6 j0 C q3 L1 O* @" N - while(differ < 0xffff-5){ //判断6 F+ [- ~& j+ Z7 P W3 D
- //查询计数器的计数值1 Z r. S3 y% _# Q/ S/ v
- differ = __HAL_TIM_GET_COUNTER(&htim7);
# v3 ]8 U* }$ |" v- J/ z - }
5 ~6 H7 q+ f/ R; Q$ Z" J) u/ K |; u - HAL_TIM_Base_Stop(&htim7);8 p5 o3 C) k8 r
- }
复制代码 . m) ` ~) g7 e* }, Y! d" D8 @
➡️ 创建DHT11温湿度传感器驱动文件DHT11.c 和相关头文件DHT11.h - void DHT11_IO_IN(void){ //IO口方向设置为输入
# n' w! f. S6 R - GPIO_InitTypeDef GPIO_InitStructure;2 ^: e7 R3 R- T2 y' L& ?% E0 k7 M' b
- GPIO_InitStructure.Pin = GPIO_PIN_11;# B; h$ \& K! p
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
# B8 L7 z& \& G' i0 a6 O - HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);1 f+ h- ~% V& A* ?0 w
- }
+ q- ?# s3 N# m' y: G j - . ^' Q3 I6 Z4 }0 ]
- void DHT11_IO_OUT(void){ //IO口方向设置为输出
5 t& F' _2 D+ D' o9 m! Z - GPIO_InitTypeDef GPIO_InitStructure;" w' b( D8 W) X, u3 S5 k9 W
- GPIO_InitStructure.Pin = GPIO_PIN_11;/ y, h" y3 P% C- [
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;5 u M: Y9 i1 `$ K/ g- s; E$ P
- GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;. z/ R$ J$ l6 Z$ Q# w8 e! A
- HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
8 y' X* x% i6 }% y9 ]. w - }
8 B) x! Z: m- ?) i - " Z9 c( ?+ W& t* i) Z
- void DHT11_Rst(void){ ! M# L" d, k9 i* D/ Y
- DHT11_IO_OUT(); //设置为输出
& A3 R4 X- `$ Y9 s - DHT11_DQ_OUT_LOW; //拉低! k1 {2 F# y4 u, Z
- HAL_Delay(20); //至少18ms5 Z0 U C' t5 ~
- DHT11_DQ_OUT_HIGH; //拉高
2 c9 l; ]3 a. u' d6 o0 H$ a - delay_us(30); //至少20~40us! D+ F( ?$ z6 c- O1 }9 n# V) p1 W+ O
- }! x. r. D5 s, c+ `) {, l% K% F
- " Y( J$ }$ a& p! s" k0 V
- uint8_t DHT11_Check(void){ 0 s/ G, I i) \; l- ~! i) J
- uint8_t retry=0;6 [/ n) Z# ]" R: M; r: {; X: s
- DHT11_IO_IN(); # }+ H ]- ]+ v- m& [) k2 x
- while (DHT11_DQ_IN&&retry<100){ //拉低40~80us3 D* q7 W; X6 z" \* E/ Q% e# Y
- retry++;
7 D5 n: w; C* ~& r. B3 U# J1 ?; M$ ~ - delay_us(1);
. `, n( m, t3 y0 s4 h3 Y - }; 8 V& F u( k6 z+ i' ]) z6 [' V1 b
- if(retry>=100)return 1;
( M; d- E" I& G# k2 V+ y - else retry=0;
/ O! z9 i2 ]# k6 n+ R( t0 J! ]8 U - while (!DHT11_DQ_IN&&retry<100){ //拉高40~80us5 s, A& u" f' r v F- {
- retry++;0 X5 J$ t4 S' g
- delay_us(1);
. y7 J w9 h: E9 k0 ]0 q - };' \, j. `( G' r6 s2 @
- if(retry>=100)return 1;
: U8 |' }9 x" {3 u, R; W - return 0; //检测到DHT11返回0
' |% `$ d2 f! i8 _% J0 {3 ~4 V: s - }
8 G- J/ W( Z; R8 M+ M8 R4 G7 x - 9 r, f: y* S' ?3 V7 H+ B
- uint8_t DHT11_Read_Bit(void){
' |0 a. h& K" T - uint8_t retry=0;
; j( x8 e+ Z$ J5 ?7 v$ f3 I - while(DHT11_DQ_IN&&retry<100){//等待变为低电平
; x- u5 m- i! i0 ?3 H0 v$ B$ ] - retry++;
Q0 k" B5 j+ S, p; `0 ? - delay_us(1);4 i5 N4 v5 g0 [0 L: U _/ T H
- }
; j5 D; b( s0 b. ]" t1 N - retry=0;4 L& S+ N% h/ n0 X
- while(!DHT11_DQ_IN&&retry<100){//等待变为高电平
}2 ?9 s0 G' J' J# {5 R2 r - retry++;
/ W+ x9 a( C/ W: P& \6 `) y - delay_us(1);/ C6 [; d" _3 @! j
- }- V1 G1 I, ~% Z+ c# M
- delay_us(40); //等待40us
+ q U7 p# [: Q5 R; d - if(DHT11_DQ_IN)return 1;8 U3 F1 i, o: l
- else return 0;
7 {' {8 H- |( Y" [9 h2 E% m - }+ z1 O0 h' Q, e c5 U: n
) m, X$ ~) m' l0 _; X$ |- uint8_t DHT11_Read_Byte(void){ - f1 a1 _9 j- a9 l
- uint8_t i,dat;
8 p2 c4 R- H1 z5 [- g- f+ R) T9 a - dat=0;
; l8 o8 |! S% Y8 j - for (i=0;i<8;i++){0 N- z* C: M/ Y9 N" B
- dat<<=1;
: J5 ]5 _2 B! m - dat|=DHT11_Read_Bit();& {$ D, D) O+ C3 K
- }
0 n% |7 M+ x3 N8 C$ ] - return dat;
8 t0 u: n+ s; T, i1 R - }
3 R- f% G1 K/ q4 b. h$ x - & n% i7 k: W$ ?) o4 O
- uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi){
+ U( H4 w4 d' v$ @& [' e8 }# U$ B - uint8_t buf[5];
* x) N& Q3 c' \0 C6 Z - uint8_t i;
. d% m2 j/ k/ h2 Z- ]; J9 r$ r7 x' ~ - DHT11_Rst();) h0 V! W [+ C7 m3 i0 B; B- Y
- if(DHT11_Check()==0){
3 L+ E- C- x J0 s - for(i=0;i<5;i++){
9 c0 u6 p1 o' a# r+ q8 g/ L# V - buf[i]=DHT11_Read_Byte();5 ~5 d, q; y3 g
- }
1 }+ u7 G. l4 K1 o - if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){
% c# a2 I! k, ^1 h% i7 G - *humi=(buf[0]<<8) + buf[1];( y! Z# N) `& {
- *temp=(buf[2]<<8) + buf[3];
0 {$ d% X- D$ ^: p - }
* M0 @$ X$ [2 G5 W, y$ v r - }else return 1;, i" m( v& u M4 @% f2 V& u
- return 0;
5 g0 z: w: ?- \9 a" B - }
7 f8 R7 ~) F9 z* K0 C+ C0 u @4 k -
( L8 L1 P7 g7 Y/ N' L - uint8_t DHT11_Init(void){
! d; h8 r' h' D: ]- i( O" b6 e - //PG11的初始化已经在cubemx中完成,可以忽略此段初始化代码
# @0 q/ i2 k7 T% v, X3 Y - GPIO_InitTypeDef GPIO_Initure; 5 `/ q( A! \+ a+ C$ q
- __HAL_RCC_GPIOG_CLK_ENABLE();
+ D" a( j3 \0 z+ ^$ }* u% H* e8 e0 g; L - GPIO_Initure.Pin=GPIO_PIN_11; : E% B) l& Q* H% a
- GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; 6 M( L: k* I7 i4 A J
- GPIO_Initure.Pull=GPIO_PULLUP;
$ A# C* E$ @4 Y/ x* a& e$ t6 z9 N0 z, { - GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
- ~; ^* [/ G. R3 Y - HAL_GPIO_Init(GPIOG,&GPIO_Initure);
1 C1 F7 _* D O4 K - DHT11_Rst();, k; i8 C4 }' R1 Q8 h
- return DHT11_Check();) ]& _( K8 H/ y7 A* T% N
- }
复制代码
. d, M+ n* ~6 Y* `9 n+ X➡️ 在main.c文件下编写DHT11测试代码 - int main(void){
" N; T/ |/ v7 m) [- i9 m: @ - /* USER CODE BEGIN 1 */
" h) v" T2 B" i, Z U) T, k/ y7 y - uint16_t temperature;
& \9 I5 h, A" j8 F( K+ v - uint16_t humidity;8 |$ b9 F, e% g3 f% R7 M$ M1 X) T9 H
- /* USER CODE END 1 */, L. }# }6 Q4 j$ h+ ?! ]5 y* h
- HAL_Init();
+ p4 a! C7 U5 z$ u$ m8 ] - SystemClock_Config();7 @ \+ p3 r: H- A6 l" s
- MX_GPIO_Init();
+ x+ n# f' n* q. z7 k( J - MX_TIM7_Init();
( u9 Y/ ?- F& i5 d - MX_USART1_UART_Init();; j" f7 p! ?5 {/ w
- /* USER CODE BEGIN 2 */
6 c$ m T0 @2 S1 v- \) d! g, A - while(DHT11_Init()){
$ R. v# m: ]2 p1 Y' b- z - printf("DHT11 Checked failed!!!\r\n");
. I. n- ?+ ]$ T) K5 }& E - HAL_Delay(500);
7 |0 g, ?: p& H+ ~9 [3 V5 F) r9 g/ a+ y - }& Z, M7 j! R2 K% \8 ?' E
- printf("DHT11 Checked Sucess!!!\r\n");( H8 R' g3 F4 g6 I, ^+ ~
- /* USER CODE END 2 */1 D8 p: {/ H) F5 G( u( ?2 w
- while (1){0 E9 K. [- q1 J$ @" `, S% \
- DHT11_Read_Data(&temperature,&humidity);
% E$ M4 c! j( y - printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);( T, J3 v- [7 u4 }7 N! g
- printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);
3 @+ v& }5 C& J - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
% T+ J/ u( s" g. A" l: T - HAL_Delay(500);
4 R1 W/ |/ \8 y4 y2 u/ A' r - }* {- h2 F4 M- e3 K
- }
复制代码 3 C0 m* ?# T1 H: a
4.下载验证 编译无误下载到开发板后,可以看到D1指示灯不断闪烁,串口不断打印出当前温湿度值。串口输出如下信息: DHT11 Checked Sucess!!! DHT11 Temperature = 28.20 degree DHT11 Humidity = 30.21% 转载自: 嵌入式攻城狮# c' n5 ~/ g, Y
如有侵权请联系删除
/ T$ O$ R7 o# m4 Y0 z! D8 c$ i
9 g$ J* O# h S# T8 Z7 j9 O0 |0 v1 r0 Y' T0 v; i
|