正点原子 发表于 2019-6-10 11:47:26

【正点原子FPGA连载】第二十六章 DHT11数字温湿度传感器实验--摘自【正点原子】开拓者 FPGA 开发指南

本帖最后由 正点原子 于 2020-10-23 11:50 编辑

1)实验平台:正点原子开拓者FPGA开发板
2)平台购买地址:https://item.taobao.com/item.htm?id=579749209820
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-281143-1-1.html
4)本实例源码下载:
5)对正点原子FPGA感兴趣的同学可以加群讨论:712557122点击加入:
6)关注正点原子公众号,获取最新资料更新:

第二十六章 DHT11数字温湿度传感器实验

DHT11是奥松(AoSong)公司生产的一款数字温湿度复合传感器。 该传感器用途广泛、 抗干扰能力强、 可靠性高, 在家电、汽车、医疗等方面有广泛的应用。本章我们将使用FPGA开发板实现对DHT11数据的采集, 并将温湿度数据显示在数码管上。
本章包括以下几个部分:
26.1 DHT11简介
26.2 实验任务
26.3 硬件设计
26.4 程序设计
26.5 下载验证


26.1 DHT11简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它使用专用的数字模块采集技术和温湿度传感技术,具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC(负温度系数热敏电阻器)测温元件,并与一个高性能8位MCU
相连接。每个DHT11传感器都在湿度校验室中校准过,校准系数以程序的形式储存在OTP(一次性可编程)内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。 DHT11使用单线制串行接口, 4针单排引脚封装,信号传输距离可达20米以上,在各类应用甚至很苛刻的环
境中都能正常工作。




图 26.1.1 DHT11内部原理图

上图为DHT11的内部原理图, 可以看出感湿原件、 感温元件和OTP内存直接连接在内部一个八位MCU上, 该MCU通过计算得出测量数值。DATA用于FPGA与DHT11之间的通讯和同步, 采用单总线数据格式, 一次通讯时间4ms左右,数据分为整数部分和小数部分, 数据格式如下:
一次完整的数据传输为40bit, 高位在前。数据格式: 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和数据数据传送正确时校验和数据等于“8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据”所得结果的末8位) 。
接下来我们介绍一下DHT11的传输时序, DHT11的数据发送流程如图 26.1.2错误!未找到引用源。 所示。



图 26.1.2 DHT11数据发送流程

主机(此处指FPGA) 首先发送一次开始信号, 即:拉低数据线,保持t1(至少18ms)时间;然后拉高数据线保持t2(20~40us)时间, 随后开始读取DHT11的响应; 如果操作正确的话, DHT11会拉低数据线,保持t3(80us)时间,作为响应信号; 接下来DHT11会拉高数据线,保持t4(80us)时间,随后开始输出有效数据。DHT11共输出40bit有效数据,每1bit数据都是以50us低电平开始,高电平的持续时间作为判断数据位的条件。 当数据位为0时,高电平的持续时间为26~28us;当数据位为1时,高电平的持续时间为70us。DHT11数据位“0”时序图和数据位“1”时序图如图 26.1.3和图 26.1.4所示。





图 26.1.3 DHT11数据位“0”时序图



图 26.1.4 DHT11数据位“1”时序图

需要注意的是, DHT11的温度和湿度转换较慢,如果读取速度过快会导致DHT11无法响应的情况。本次实验每100ms读取一次,如果DHT11长时间未响应,则重新发起开始信号。
26.2 实验任务
本节实验任务是使用开拓者FPGA开发板完成对DHT11温湿度数据的采集, 并通过按键KEY0控制温度和湿度在数码管上的切换显示。
26.3 硬件设计
我们的开拓者开发板上有一个DS18B20/DTH11的扩展接口, 该接口可以用来连接DS18B20或DHT11。其原理图如图 26.3.1所示。



图 26.3.1 DHT11/DS18B20扩展接口原理图

DHT11通过4个排针与外部连接,如图 26.3.2所示,将DHT11直接插在开发板上即可,接插之前注意正负极的方向, 以免短路。





图 26.3.2 开发板插口实物图

本次实验的管脚分配如下表所示:
表 26.3.1 管脚分配










26.4 程序设计
根据实验任务,我们可以大致规划出系统的工作流程: FPGA控制DHT11采集温度和湿度,并将收到的温度和湿度数据转换成十进制显示在数码管上。本次实验使用按键来控制数码管显示温度和湿度,所以还需要添加消抖模块来对按键进行消抖,以及按键控制模块控制数码管切
换显示温度和湿度。 由此画出的系统框图如下图所示。




图 26.4.1 DHT11数字温湿度传感器系统框图

各模块端口及信号连接如图 26.4.2所示:



图 26.4.2 顶层模块原理图


FPGA部分包括5个模块, 顶层模块(top_dht11)、 DHT11驱动模块(dht11_drive) 、按键消抖模块(key_debounce) 、按键控制模块(dht11_key) 、 数码管驱动模块(seg_led) 。其中在顶层模块完成对其他模块的例化。DHT11驱动模块(dht11_drive) : dht11_drive模块通过单总线引脚读取DHT11的温度值和湿度值,并将读取到的数据输出至按键控制模块。按键消抖模块(key_debounce) : 消除按键抖动,在检测到有按键按下或释放时对按键数据进行消抖处理。按键控制模块(dht11_key):根据输入的按键控制信号,将温度数据和湿度数据选择输出至数码管显示模块。数码管显示模块(seg_led):将输入的数据显示到数码管上。顶层模块代码如下:
1 module top_dht11(
2 input sys_clk , //系统时钟
3 input sys_rst_n , //系统复位
4 5
input key , //按键
6 inout dht11 , //dht11总线
7 output sel , //数码管位选信号
8 output seg_led //数码管段选信号
9 );
10 //wire define
11 wire data_valid;
12 wire data ;
13 wire point ;
14
15 //*****************************************************
16 //** main code
17 //*****************************************************
18
19 //dht11驱动模块
20 dht11_drive u_dht11_drive (
21 .sys_clk (sys_clk) ,
22 .rst_n (sys_rst_n),
23 .dht11 (dht11) ,
24 .data_valid (data_valid)
25 );
26
27 //数码管模块
28 seg_led u_seg_led (
29 .clk (sys_clk),
30 .rst_n (sys_rst_n),
31 .sel (sel),
32 .seg_led (seg_led),
33 .data (data),
34 .point (point),
35 .en (en),
36 .sign (sign)
37 );
38
39 //消抖模块
40 key_debounce u_key_debounce(
41 .sys_clk (sys_clk),
42 .sys_rst_n (sys_rst_n),
43 .key (key),
44 .key_flag (key_flag),
45 .key_value (key_value)
46 );
47
48 //按键控制
49 dht11_key u_dht11_key(
50 .sys_clk (sys_clk), //系统时钟
51 .sys_rst_n (sys_rst_n), //系统复位
52 .key_flag (key_flag), //按键有效
53 .key_value (key_value),
54 .data_valid (data_valid),
55 .data (data),
56 .sign (sign),
57 .en (en),
58 .point (point)
59 );
60
61 endmodule
顶层模块完成对其他模块的例化, dht11_drivr模块输出的数据信号(data_valid) 和key_debounce模块输出的按键信号(key_flag和key_value)连接至dht11_key模块, dht11_key模块输出的温度/湿度数据(data)以及数码管控制信号连接至seg_led模块。
由本章简介部分介绍的DHT11传输时序可以发现, DHT11的传输时序适合用状态机来编写。DHT11驱动模块状态跳转图如下所示。




图 26.4.3 DHT11驱动状态跳转图

DHT11驱动模块使用三段式状态机来读取DHT11的温度和湿度值,从上图可以比较直观的看到每个状态实现的功能以及跳转都下一个状态的条件。这里需要注意的一点是,由于DHT11温度 和 湿 度 转 换 较 慢 , 如 果 读 取 速 度 过 快 会 导 致 DHT11 无 法 响 应 的 情 况 , 所 以 我 们 在
st_rec_low_80us状态做了响应超时处理,如果DHT11长时间未响应,则重新发起开始信号。由于DHT11驱动模块的代码较长,我们仅贴出部分源代码。
216 st_low_18ms: begin
217 dht11_buffer <= 1'b0; //给总线低电平
218 if(us_cnt == 18000) //发送18ms的低电平
219 delay_done <= 1'b1;
220 if(delay_done) begin
221 us_cnt_clr <= 1'b1;
222 dht11_buffer <= 1'bz;
223 end
224 end
225 st_high_20us:begin //等待20~40us
226 if (us_cnt == 20)
227 delay_done <= 1'b1;
228 if(delay_done)
229 us_cnt_clr <= 1'b1;
230 end
231 st_rec_low_80us: begin //接收dht11的低电平响应
232 case(step_cnt)
233 0 : begin
234 if(!dht11)
235 step_cnt <= step_cnt + 1'b1;
236 end
237 1: begin
238 if(dht11_pos) begin
239 if(us_cnt >= 60)
240 rec_done <= 1'b1;
241 end
242 end
243 default : ;
244 endcase
245 if(us_cnt >= 100_000) //超过100ms未应答,重新发起
246 restart_en <= 1'b1;
247 if(rec_done || restart_en) begin
248 us_cnt_clr <= 1'b1;
249 step_cnt <= 3'b0;
250 end
251 end
252 st_rec_high_80us: begin //接收dht11的高电平响应
253 case(step_cnt)
254 0 : begin
255 if(dht11)
256 step_cnt <= step_cnt + 1'b1;
257 end
258 1: begin
259 if(dht11_neg) begin
260 if(us_cnt >= 70)
261 rec_done <= 1'b1;
262 end
263 end
264 default : ;
265 endcase
266 if(rec_done) begin
267 us_cnt_clr <= 1'b1;
268 step_cnt <= 3'b0;
269 end
270 end
从代码的第245行可知,在st_rec_low_80us状态下,当DHT11长时间未响应时(超时100ms),拉高restart_en信号, 重新发起开始信号。
图 26.4.4为SignalTap抓取的波形图,从图中可以清晰的看到DHT11驱动模块各个状态跳转的波形图。 st_rec_data为解析数据的状态,数据解析完成之后,开始进入st_delay(延时)状态, 延时状态结束之后,准备重新发起开始信号。



图 26.4.4 SignalTap抓取的波形图

按键控制模块的代码如下所示:
1 module dht11_key(
2 input sys_clk , //系统时钟
3 input sys_rst_n , //系统复位
4 5
input key_flag , //按键有效
6 input key_value ,
7 input data_valid ,
8 output data ,
9 output reg sign ,
10 output reg en ,
11 output reg point
12 );
13
14 //reg define
15 reg flag ;
16 reg data0;
17 reg data1;
18
19 //*****************************************************
20 //** main code
21 //*****************************************************
22
23 //采集按键上升沿
24 assign key_pos = (~key_value) & key_flag;
25 //由于要显示的数值由整数部分和小数部分组成,所以需要合并起来
26 assign data = data1 * 100 + data0*10;
27
28 //确定显示的数据是温度值还是湿度值, flag为“0” 时显示温度,为“1” 时显示湿度
29 always @ (posedge sys_clk or negedge sys_rst_n) begin
30 if(!sys_rst_n)
31 flag <= 1'b0;
32 else if (key_pos)
33 flag <= flag + 1'b1;
34 end
35
36 always @ (posedge sys_clk or negedge sys_rst_n) begin
37 if(!sys_rst_n) begin
38 data0 <= 8'b0;
39 data1 <= 8'b0;
40 end
41 else if (flag == 1'b0) begin
42 data1 <= data_valid;
43 data0 <= data_valid;
44 end
45 else begin
46 data1 <= data_valid;
47 data0 <= data_valid;
48 end
49 end
50
51 //确定小数点显示的位置,这里在百位显示小数点
52 always @ (posedge sys_clk or negedge sys_rst_n) begin
53 if(!sys_rst_n) begin
54 point <= 6'b111111;
55 en <= 1'b0;
56 sign <= 1'b0;
57 end
58 else begin
59 point <= 6'b000100;
60 en <= 1'b1;
61 sign <= 1'b0;
62 end
63 end
64
65 endmodule

在代码的第29行开始的always中,每按下一次按键KEY0, flag的值会改变一次,当flag的值等于0时,输出的值为温度值;当flag的值等于1时,输出的值为湿度值。在代码的第26行中,我们将温湿度值的整数部分放大100倍,小数部分放大10倍,显示在数码管上。按键消抖模块和数码管显示模块分别在“按键控制蜂鸣器试验”和“动态数码管显示试验”中作出了详细介绍,在此不再赘述。
26.5 下载验证
首先我们打开DHT11数字温湿度传感器实验工程, 在工程所在的路径下打开top_dht11/par文件夹, 在里面找到“top_dht11.qpf” 并双击打开。注意工程所在的路径名只能由字母、 数字以及下划线组成, 不能出现中文、空格以及特殊字符等。工程打开后如图 26.5.1所示。



图 26.5.1 DHT11工程打开界面

将DHT11接插到开拓者开发板上的单总线接口,如下图所示。 然后将下载器一端连电脑,另一端与开发板上对应端口连接,最后连接电源线并打开电源开关。




图 26.5.2 DHT11接插至开拓者开发板

工程打开后通过点击工具栏中的“Programmer” 图标(图中红框位置)打开下载界面, 通过“Add File” 按钮选择DHT11数字温湿度传感器工程中top_dht11/par/output_files目录下“top_dht11.sof” 文件,下载界面如图 26.5.3所示(图中已下载完毕) 。



图 26.5.3 下载界面

接下来我们点击左侧的Start, 下载程序,验证温湿度传感器数码管显示功能。下载完成后, 数码管默认显示的是温度值,当按下KEY0按键后,数码管会显示湿度值,说明本次DHT11数字温湿度传感器实验验证成功。 这里需要注意的是温度值的单位是:℃(摄氏
度);湿度值的单位是: %RH(相对湿度),温度值和湿度值的单位在数码管上没有显示。



图 26.5.4 开发板KEY0按键



页: [1]
查看完整版本: 【正点原子FPGA连载】第二十六章 DHT11数字温湿度传感器实验--摘自【正点原子】开拓者 FPGA 开发指南